3

我试图让我们的聊天系统支持 UTF-8,但我失败了。如果在客户端,我发送以下消息,通过encodeURIComponent

  • ûôó

并将其放在 PHP 端:

error_log(print_r(array(
    $_POST['message'],
    urldecode($_POST['message']),
    rawurldecode($_POST['message']),
    utf8_decode($_POST['message']),
    utf8_decode(urldecode($_POST['message'])),
    utf8_decode(rawurldecode($_POST['message']))
), true));

这是我的错误日志中的输出:

Array
(
    [0] => %C3%AE%C3%BB%C3%B4%C3%B3
    [1] => îûôó
    [2] => îûôó
    [3] => %C3%AE%C3%BB%C3%B4%C3%B3
    [4] => îûôó
    [5] => îûôó
)

所以一切都很好。但是,如果我使用这些,都从 Wikipedia 复制(分别为俄语和日语页面):

  • русский язык
  • 日本语</li>

这一切都下地狱了!

Array
(
    [0] => %D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%20%D1%8F%D0%B7%D1%8B%D0%BA
    [1] => руÑÑкий Ñзык
    [2] => руÑÑкий Ñзык
    [3] => %D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%20%D1%8F%D0%B7%D1%8B%D0%BA
    [4] => ??????? ????
    [5] => ??????? ????
)
Array
(
    [0] => %E6%97%A5%E6%9C%AC%E8%AA%9E
    [1] => 日本語
    [2] => 日本語
    [3] => %E6%97%A5%E6%9C%AC%E8%AA%9E
    [4] => ???
    [5] => ???
)

我需要做什么才能完成这项工作?

4

2 回答 2

2
$_POST['message'], => [0] => %C3%AE%C3%BB%C3%B4%C3%B3

您对输入进行了过度 URL 编码。GET/POST/REQUEST 超全局变量已经在必要时处理了 URL 解码输入字符串,您不需要手动对它们进行 URL 解码。

查看导致此请求的原因(XMLHttpRequest?)并删除对encodeURIComponent(). 例如,如果您使用 jQueryajax()并将 POST-data 作为对象传递,jQuery 会encodeURIComponent()为您调用,您也不需要自己做。

urldecode($_POST['message']), => îûôó

这是 UTF-8 被误解为 Windows 代码页 1252(西欧,类似于 ISO-8859-1)。

很可能您已成功将 UTF-8 字节保存到日志文件中,但无论您在其中读取日志文件,都没有意识到它应该呈现为 UTF-8。

utf8_decode(urldecode($_POST['message'])), => îûôó

这只有效,因为您用来测试它的字符也存在于代码页 1252utf8_decode中。它实际上所做的是将 UTF-8 字节序列转换为表示相同字符串的 ISO-8859-1 字节序列。您通常希望使用 UTF-8 而不是 ISO-8859-1,因此通常应避免使用 utf8_decode。

русский язык => ??????? ????

可以理解:代码页 1252 中不存在西里尔字符。

假设您将 error_log 输出发送到一个文件,并尝试读取该文件,坚持使用纯 UTF-8 字节,并在一个体面的文本编辑器中读取您的日志,该编辑器可让您查看和选择编码;理想情况下是默认为 UTF-8 的现代版本。或者,您可以通过另存为 UTF-16 或 UTF-8 并在开头包含字节顺序标记来说服记事本读取 Unicode 文件。(在 UTF-8 文件中包含 BOM 是错误的,但 Microsoft 世界中的许多工具都这样做。)

于 2011-11-01T17:59:17.520 回答
2

在整个堆栈中使用 UTF8:

  • 数据库表
  • 数据库连接
  • PHP默认字符集设置
  • 字符串函数

数据库表:

将 db 排序规则设置为utf8_unicode_ci.
将所有 text/varchar 字段设置为utf8_unicode_ci.
通过执行以下查询将数据库连接设置为 UTF-8:

SET NAMES 'utf8'

PHP 字符集

利用:

ini_set('default_charset', 'utf-8'); 

PHP 字符串函数

一些 PHP 字符串函数不是二进制安全的,因此您需要使用 mb_* 等效项。

例如mb_strlen,而不是strlen

HTML:

使用元标记设置字符集:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
于 2011-11-01T17:15:00.967 回答