【问题标题】:PHP/MySQL encoding problems. â�� instead of certain charactersPHP/MySQL 编码问题。 â��而不是某些字符
【发布时间】:2012-10-10 16:38:17
【问题描述】:

我在使用 php 将某些字符输入到我的 mysql 数据库时遇到了一些问题。我正在做的是将用户输入的文本提交到数据库。我无法弄清楚我需要更改什么以允许将任何类型的字符放入数据库并通过 php 打印出来。

我的 MySQL 排序规则是:latin1_swedish_ci

就在我将文本从表单发送到数据库之前,我在数据上使用了 mysql_real_escape_string()。

以下示例

这段文字:

�People are just as happy as they make up their minds to be.�
� Abraham Lincoln 

假设看起来像这样:

“People are just as happy as they make up their minds to be.”
― Abraham Lincoln

【问题讨论】:

  • 为什么不使用 UTF-8 排序规则?
  • Latin1 不是 UTF-8。因此,像 这样的 latin1 未涵盖的字符被 Mojibake 处理也就不足为奇了。
  • latin1 是我猜的默认值,我从来没有,也仍然不明白哪种排序规则最适合使用,所以我一直使用它。我之前尝试过 UTF-8 排序规则,但似乎没有解决问题
  • 那是因为它不是完整的解决方案。您的整个程序从头到尾都需要使用 UTF-8。
  • 请注意,表排序规则与表字符集不同。排序规则仅定义字符的排序顺序(通常取决于区域设置,例如瑞典语,因为您最初在那里)。因此,即使您尝试使用 UTF-8 的表排序规则,如果您不使用 UTF-8 的表字符集,它也不会接受 UTF-8 字符。

标签: php mysql utf-8 character-encoding collation


【解决方案1】:

正如其他人所说,如果要支持“特殊”字符,则需要从头到尾转换为 UTF8。这意味着您的网页、PHP、mysql 连接和 mysql 表。网页相当简单,只需使用 UTF8 的元标记。理想情况下,您的标头也会显示 UTF8。

<meta http-equiv="content-type" content="text/html; charset=utf-8" />

将您的 PHP 设置为使用 UTF8。无论如何,事情可能会奏效,但这样做是一个很好的措施:

mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
mb_http_input('UTF-8');

对于mysql,你想将你的表转换为UTF8,不需要导出/导入。

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8

您可以而且应该将 mysql 配置为默认 utf8。但你也可以运行查询:

 SET NAMES UTF8

作为建立连接后的第一个查询,它将您的数据库连接“转换”为 UTF8。

这应该可以解决你所有的字符显示问题。

【讨论】:

  • 当页面通过 HTTP 提供时,元标记将被忽略。它仅在从本地磁盘文件系统打开页面时使用。标头比元标记更重要。
  • 谢谢,我会完成所有这些。尽管我已经完成了大部分这些步骤,但没有成功,或者完全成功,
  • 您只需错过 1 个步骤即可使其失败。如果 mysql 未配置为完全 utf8,则 SET NAMES UTF8 查询非常重要。
  • 好的,谢谢,我已经在我的 php 中设置了这些东西,但是似乎没有工作。我也确实在我的数据库中运行了该更改表代码。我有一个名为 connect.php 的文件,它包含在我进行 mysql 查询往返的每个页面中,这个页面是我连接和选择我的数据库的地方。我在其中添加了这些行但没有成功: mysql_query("SET NAMES 'utf8'"); mb_internal_encoding('UTF-8'); mb_http_output('UTF-8'); mb_http_input('UTF-8');
  • 嗯实际上似乎我已经让它正常工作,只要将数据插入到 MYSQL,我认为这是因为在数据库中不再有来自字符的所有垃圾,它只是有实际显示的字符应有的样子。现在的问题似乎是将数据回显到页面上,我尝试了 utf8_decode 但这似乎并没有做任何事情,所以嗯,我被这部分难住了。
【解决方案2】:

问题的最可能原因是数据库 connection 设置为 latin1,但您输入的是 UTF-8 编码的文本。解决这个问题的最简单方法是将您的输入转换为客户的期望:

$quote = iconv("UTF-8", "WINDOWS-1252//TRANSLIT", $quote);

(MySQL 调用的latin1 在世界其他地方是 windows-1252。)请注意,许多字符,例如您在那里使用的引号 U+2015,不能用这种编码表示,并且将被转换变成别的东西。理想情况下,您应该将列编码更改为utf8

另一种解决方案:将数据库连接设置为utf8。列的编码方式无关紧要:MySQL 在内部将文本从连接编码转换为存储编码,如果您愿意,可以将列保留为 latin1。 (如果这样做,引号 U+2015 将变成问号?,因为它不在latin1 中)

如何设置连接编码取决于您使用的库:如果您使用已弃用的 MySQL 库,则为 mysql_set_charset,如果使用 MySQLi,则为 mysqli_set_charset,如果 PDO 将 encoding=utf8 添加到 DSN。

如果您这样做,您将使用 Content-Type 标头将页面编码设置为 UTF-8。 否则你会在浏览器上遇到同样的问题:当它期待别的东西时,给它输入 UTF-8 编码的文本:

header("Content-Type: text/html; charset=utf-8");

【讨论】:

  • 我已经完成并尝试了答案之一所建议的所有内容(布伦特的),但无法让它发挥作用,但我尝试使用 mysql_set_charset("utf8"); (这是我使用的库),但这也没有解决问题。我经历了一切,没有任何运气:\
  • 嗯实际上似乎我已经让它正常工作,只要将数据插入到 MYSQL,我认为这是因为在数据库中不再有来自字符的所有垃圾,它只是有实际显示的字符应有的样子。现在的问题似乎是将数据回显到页面上,我尝试了 utf8_decode 但这似乎并没有做任何事情,所以嗯,我被这部分难住了。
  • 检查 Web 浏览器使用哪种编码来显示页面 - 它应该是那种编码吗?您是否设置了 Content Type 标头?
  • 它是否仍然显示 â�� 而不是一个弯引号,或者只是一个 �?
  • 哦,该死的,是我在返回的字符串上使用了“htmlentities()”导致了那个..嗯,我很确定我需要使用那个函数,或者一个类似的函数,而不会破坏 utf8 字符。
【解决方案3】:

提供的解决方案很有帮助如果从头开始。将所有可能的连接都放到 UTF-8 确实是最安全的。由于各种原因,UTF-8 是网络上最常用的字符集。

一些建议和警告:

  • 复制您要使用唯一前缀 (tmp_) 清理的表
  • 虽然您的 db-connection 强制为 utf8,但请检查您的 General Settings 排序规则,如果尚未完成,请更改为 utf8_bin
  • 您需要在本地服务器上运行它
  • 有趣的字符错误主要是由于混合了 LATIN1 和 UTF-8 配置。该解决方案就是为此而设计的。它可以与 LATIN1 的其他使用过的字符集一起使用,但我没有检查过这个
  • 检查这些 tmp_tables 广泛地复制回原来的

构建魔术所需的 2 数组:

$chars = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES, "UTF-8");
$LATIN1 = $UTF8 = array();
while (list($key,$val) = each ($chars)) {
    $UTF8[] = $key;
    $LATIN1[] = $val;
}

现在建立您需要的例程:(tables->)rows->fields 和在每个字段调用时

$row[$field] = mysql_real_escape_string(str_replace($LATIN1 , $UTF8 , $row[$field]));
$q[] = "$field = '{$row[$field]}'";

最后构建并发送查询:

mysql_query("UPDATE $table SET " . implode(" , " , $q) . " WHERE id = '{$row['id']}' LIMIT 1");

【讨论】:

    【解决方案4】:

    将 MySQL 排序规则更改为 utf8_unicode_ci 或 utf8_general_ci,包括表和数据库。

    【讨论】:

    • 谢谢,我现在已经这样做了,它似乎对这个问题没有任何影响:\
    • 当然不是,排序规则只是定义了字符的排序顺序。例如。 áä 之前或相反。它没有定义表实际使用的字符集。为此,您需要更改表格字符集。
    • 我不知道这是否有帮助,但我使用这些信息将排序规则更改为二进制,因为我想保留每个字符的值并且它对我有用。
    【解决方案5】:

    您需要将数据库设置为 utf-8 是的。有很多方法可以做到这一点。通过更改配置文件,通过 phpmyadmin 或在插入和更新 mysql 之前调用 php 函数(抱歉内存空白)。

    很遗憾,我认为您必须重新输入之前输入的所有数据。

    根据个人经验,您还需要知道一件事,确保所有具有关系的表都具有相同的排序规则,否则您将无法加入它们。

    作为参考:http://dev.mysql.com/doc/refman/5.6/en/charset-syntax.html

    另外,我可以是 apache 设置。我们在“免费托管”服务器和我兄弟的服务器上都遇到了同样的问题。一旦切换到另一台服务器,所有字符都变得整洁。验证你的 apache 设置,抱歉,我不能更清楚 apache 的配置。

    【讨论】:

      【解决方案6】:

      摆脱一切只需要遵循这两点,所有关于特殊语言字符的问题都会迎刃而解。

      1- 您需要将表的排序规则定义为 utf8_general_ci。

      2- 在 HTML 的 head 标签后面定义&lt;meta http-equiv="content-type" content="text/html; charset=utf-8"&gt;

      2- 您需要在与数据库建立连接的文件中定义mysql_set_charset('utf8',$link_identifier);,并在选择“mysql_select_db”等数据库后立即使用“mysql_set_charset”,这将允许您在其中正确添加和检索数据不管是什么语言。

      【讨论】:

        【解决方案7】:

        如果您的文本已使用错误的编码进行编码和解码,因此 mojibake 实际上被“固化”为 unicode 字符,那么到目前为止提到的解决方案将不起作用。我最终成功地使用了ftfy Python 包来自动检测/修复 mojibake:

        >>> import ftfy
        >>> print(ftfy.fix_encoding("(ง'⌣')ง"))
        (ง'⌣')ง
        

        希望这对处于类似情况的人有所帮助。

        【讨论】:

          猜你喜欢
          • 2010-11-30
          • 2011-04-04
          • 2015-12-31
          • 2016-10-20
          • 2015-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多