【问题标题】:Changing character encoding in MySQL, PHP scripts, HTML更改 MySQL、PHP 脚本、HTML 中的字符编码
【发布时间】:2011-02-28 15:06:04
【问题描述】:

所以,我已经在这个系统上构建了很长时间,它目前正在将 Latin1 (ISO-8859-1) 输出到 Web 浏览器,这是组件:

MySQL - 所有数据都以 Latin1 字符集存储

PHP - 所有 PHP 文本文件都以 Latin1 编码存储在磁盘上

HTML - 输出包含 http-equiv="content-type" content="text/html; charset=iso-8859-1" 元标记

所以,我试图了解不同部分的编码如何在我的工作流程中发挥作用。如果我打开一个 PHP 脚本并将其在文本编辑器中的编码更改为 UTF-8 并将其保存回磁盘并重新加载 Web 浏览器,那么文本就会一团糟——除非文本来自数据库。如果我将数据库的编码更改为 UTF-8 并将 PHP 文件保留在 latin1 中,我必须使用 utf8_decode() 才能正确显示数据。如果我更改 HTML 代码,浏览器会错误地读取它。

所以是的,我意识到如果我想“升级”到 UTF8,我必须更新此设置的所有三个部分才能使其正常工作,但由于它是一个庞大的系统,包含大约 180k 行 PHP 代码和数百万行很多数据库/表中的帖子,我不想在没有正确理解所有内容的情况下开始这样的事情。

我没有想到什么?除了修复之外,还有什么可以搞砸的?更改整个 MySQL 安装的编码的过程是什么?更改磁盘上数百或数千个 PHP 文件的编码的最简单方法是什么?

幸运的是,META 标签是动态添加的,所以我只在一处进行更改:)

让我听听你在这方面的经验。

【问题讨论】:

    标签: php mysql encoding utf-8


    【解决方案1】:

    这很棘手。

    你必须:

    • 更改数据库和每个表的字符集/编码——我对 MySQL 了解不多,但请参阅here
    • 在第一次查询之前在 PHP (SET NAMES UTF8) 中将客户端编码设置为 UTF-8
    • 更改元标记和可能的 Content-type 标头(注意 Content-type 标头优先)
    • 将所有 PHP 文件转换为不带 BOM 的 UTF-8 - 您可以使用循环和 iconv 轻松完成。
    • 最棘手的:您必须更改大部分字符串函数调用。比意味着mb_strlen 代替strlenmb_substr 代替substr$str[index] 等。

    【讨论】:

    • DB - 检查,客户端编码 - 你的意思是当通过 PHP 与 MySQL 服务器交互时?元标记 - 检查,PHP 文件 - 检查,PHP 函数...嗯,好的。虽然我很少使用 strlen 和 substr - 那 $str[index] 呢?你的意思是在写一个 UTF8 编码的 PHP 文件时,我不能写 print $foo["Översrift"] ?> 大概是字符串作为UTF8数据发送到PHP解释器,保存的索引数据应该是相同的,不是吗?
    • 只要没有来自其他地方的数据确实 $foo["Översrift"] 将继续工作,前提是所有文件都转换为 utf-8。
    • @Sandman 是的,我的意思是当通过 PHP 与 MySQL 服务器交互时。我所说的$str[index]$str[0] 之类的东西(索引是一个整数)。例如,您不能使用$str[0] 来获取第一个字符,因为 UTF-8 是一种多字节编码;如果第一个字符占用超过 1 个字节(所有非 ASCII 字符都是这种情况),$str[0] 将只获取字符的第一个字节。还有很多其他情况——大多数操作字符串的函数都必须修改。
    • 好吧,那我和你在一起。我永远不会那样使用 $str[index] :)
    【解决方案2】:

    如果没有必要,不要转换为 UTF8。这不值得麻烦。
    UTF8 是(正在成为)新标准,因此对于新项目,我可以推荐它。

    功能
    某些函数调用不再起作用。对于 latin1,它是:

     echo htmlentities($string);
    

    对于 UTF8,它是:

     echo htmlentities($string, ENT_COMPAT, 'UTF-8');
    

    strlen()、substr() 等。不知道多字节字符。

    MySQL
    mysql_set_charset('UTF8')mysql_query('SET NAMES UTF8') 会将来自数据库的所有文本转换为 UTF8 (SELECTs)。它还将传入的字符串(插入、更新)从 UTF8 转换为表的编码。

    因此,对于从 latin1 表中读取数据,无需转换表编码。
    但某些字符仅在 unicode 中可用(如雪人☃、iPhone 表情符号等),无法转换为 latin1。 (数据会被截断)

    脚本
    我尝试在我的 php 脚本/模板中防止特殊字符。
    我使用ë 表示法而不是ë 等。这样保存在latin1 或utf8 中并不重要。

    【讨论】:

    • 只要您保存的内容在其当前字符集中可用,就不必转换 MySQL 表。但是,如果不是(并且在使用 latin1 => utf8 时这种可能性不小),它们应该被转换(ALTER TABLE foo SET CHARACTER SET utf8),如果它们已经被单独设置,可能是它们自己的列。
    • 不,如果您更改连接的编码,mysql 服务器/客户端将即时转换它。
    • 如果我需要生成 ms-excel csv 文件,我会使用它。表格采用 UTF8 格式,在 SET NAMES lantin1 之后,我可以在没有单个 utf_decode() 的情况下写入 csv 文件
    • @Bob Fanger:考虑写入表,而不是读取。是的,尝试进行转换,但将 utf-8 放入 latin1 并不总是可行的,还是我弄错了?如果字符集 100% 重叠,为什么要使用一个而不是另一个?
    • @Wrikken 你没看错。显然,您不能在 latin1 列中放入不在 latin1 中的字符,例如ى。
    猜你喜欢
    • 1970-01-01
    • 2023-04-11
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 2013-09-06
    相关资源
    最近更新 更多