【问题标题】:Problem with displaying russian letters in browser even though UTF-8 encoding is set即使设置了 UTF-8 编码,在浏览器中显示俄语字母的问题
【发布时间】:2011-11-02 00:27:22
【问题描述】:

我知道有一些类似的问题。但是,在阅读了有关该主题的答案和搜索后,我仍然在努力在浏览器中显示俄语字母。我将它们存储在 .csv 文件中(以 UTF-8 编码,无 BOM)。在我的读取 .csv 的 php 文件中(也以 UTF-8 无 BOM 编码)我声明了字符集:

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

要打开和遍历 .csv 文件,我使用以下代码:

  if(($handle = fopen($path, "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
      ...
    }
  }

要么什么都没有显示,要么是这样的:

 -ам-Зее

而不是

 Целль-ам-Зее

还有什么我可以尝试的想法吗?

更新:

将浏览器编码设置为 UTF-8 后,我得到正确的俄语字母。但是,仍然有一些文本根本不显示。我怀疑我在读取 .csv 文件时做错了什么,简化版是:

     if(($handle = fopen($path, "r")) !== FALSE) {
       while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
         echo $data[1];
        }
     }

(我省略了第一列并显示第二列的内容,始终填充)

【问题讨论】:

  • 在浏览器中尝试查看 > 编码并尝试一些编码来确定您的文本的真正编码。如果它在任何编码中都没有意义,那么您可能在您省略的部分的某个地方对其进行了加扰。
  • @deceze 谢谢,这很有帮助。我完全忘记了更改浏览器编码。但是我仍然遇到问题,一些文本没有加载,我什么也没有得到文本。我会更新我的问题
  • 好像文本已经被两次utf8_encoded,你自己试试吧:cafewebmaster.com/online_tools/utf8_encode把Целль-ам-Зее放在文本框中,然后点击编码得到ЦеллÑ-ам-Ðее你在执行 utf8_encode 吗?
  • @corretge 我不是,我使用我发布的代码(我刚刚省略了逻辑)。但是,您是对的,在 utf-8 中编码 Австрия 后,我得到了相同的奇怪字符串。但是我不知道在哪里可以完成。也许在打开保存在 utf-8 中的文件时,嗯..

标签: php unicode utf-8 character-encoding


【解决方案1】:

检查您的服务器配置

您是否已将 Apache 配置为支持 &lt;meta&gt; 字符集覆盖?默认情况下,它使用 ISO-8859-1 作为其默认值并忽略它所服务的网页中出现的任何覆盖。

第 1 个解决方案,共 3 个

例如,您可以将其放在您的 .htaccess 文件中作为封闭目录,现在您的网页将使用其 &lt;meta&gt; 覆盖:

AddDefaultCharset Off
AddCharset UTF-8 .html

Apache documentation 声明:

当且仅当响应的content-type 是text/plain 或text/html 时,此指令指定要添加到响应的媒体类型字符集参数(字符编码的名称)的默认值。这应该通过 META 元素覆盖响应正文中指定的任何字符集,尽管确切的行为通常取决于用户的客户端配置。 AddDefaultCharset Off 的设置禁用此功能。 AddDefaultCharset On 启用默认字符集 iso-8859-1。假定任何其他值是要使用的字符集,它应该是用于 MIME 媒体类型的IANA registered charset values 之一。例如:

   AddDefaultCharset utf-8     

AddDefaultCharset 仅应在已知其应用的所有文本资源都采用该字符编码并且单独标记其字符集太不方便时使用。一个这样的示例是将 charset 参数添加到包含生成内容的资源中,例如遗留 CGI 脚本,由于输出中包含用户提供的数据,这些内容可能容易受到跨站点脚本攻击。但请注意,更好的解决方案是修复(或删除)这些脚本,因为设置默认字符集不会保护已在浏览器上启用“自动检测字符编码”功能的用户。

在我关闭AddDefaultCharset 之前,我无法让我的&lt;meta&gt; 标签工作。这是相当神秘和令人沮丧的。不过,一旦我这样做了,一切都很顺利。

第 2 个解决方案,共 3 个

如果您对 Apache 的配置文件具有写入权限,那么您可以更改服务器本身。但是,您必须确保没有其他东西依赖于旧的不可覆盖设置。这是使用.htaccess 的另一个原因。


当所有其他方法都失败时:解决方案 #3 of 3

如果您既不能更改整体服务器配置本身也不能创建 .htaccess 其自己的设置将在其下面的任何内容中得到尊重,那么您唯一的选择是对超过 127 的所有代码点使用数字实体。例如,改为的

Целль-ам-Зее

你必须改为使用

&#1062;&#1077;&#1083;&#1083;&#1100;-&#1072;&#1084;-&#1047;&#1077;&#1077;

或

&#x426;&#x435;&#x43B;&#x43B;&#x44C;-&#x430;&#x43C;-&#x417;&#x435;&#x435;

这样做的好处是它不再需要 &lt;meta&gt; 覆盖和摆弄服务器或 .htaccess 文件。缺点是它需要额外的翻译通道,这会干扰使用理解文字 UTF-8 的编辑器直接编辑文件的能力。

实体忽略编码

之所以起作用,是因为所有的 HTML 始终是 Unicode,所以字符编号 1062 始终是CYRILLIC CAPITAL LETTER TSE,等等。实体编号始终代表 Unicode 码位编号;它们永远不是文档编码中的数字。只有编码字节才算作服务器或页面编码,而不是始终为 Unicode 的未编码代码点编号。

这就是为什么我们可以使用 &amp;#233; 之类的东西,它总是意味着 LATIN SMALL LETTER E WITH ACUTE,因为代码点 233 始终是那个字符,即使网页本身应该采用其他编码(比如 MacRoman 中的 142 或 NextStep 中的 221)。

字符的数量总是Unicode数字,不注意编码。这是因为 HTML、XHTML 和 XML 等标记语言总是使用逻辑 Unicode 代码点编号,就像 Perl 和 Go 等编程语言一样。 (PHP 实际上只是在其上加上一些 UTF-8 API 的字节,但正如您自己了解到的那样,它仍然存在问题。这既是因为它的内部模型,也是由于 Web 服务器甚至 Web 客户端,所有这些都使得 PHP 中的一切都比大多数其他语言更复杂。)

即使您已使用 ISO-8859-1 对 Cyrillic 的网页进行编码,其中文字 0xC6 字节将 Unicode U+0426、CYRILLIC CAPITAL LETTER TSE 编码为字符实体,您仍将使用 &amp;#1062; 或 &amp;#x426; —而不是&amp;#xC6;,这是错误的,因为 U+00C6 是LATIN CAPITAL LETTER AE。

同样,如果您使用 MacCyrillic 编码,文字 0x96 字节将是 CYRILLIC CAPITAL LETTER TSE,但由于数字实体始终采用 Unicode,您必须使用 &amp;#1062; 或 &amp;#x426; — 而不是 &amp;#x96; .

我更喜欢对所有网页仅使用 UTF-8。好吧,对于新的,就是这样。我确实承认存在遗留的非 Unicode 页面。那些我就这样离开了。

【讨论】:

    【解决方案2】:

    您需要在服务器上设置正确的区域设置。

    if(!setlocale(LC_ALL, 'ru_RU.utf8')) 
        setlocale(LC_ALL, 'en_US.utf8');
    

    然后您可以检查您的服务器是否已接受所需的语言环境

    if(setlocale(LC_ALL, 0) == 'C')
        echo 'Error setting locale';
    

    问题出在使用不正确语言环境的 fgetcsv 函数中。如果您无法更改语言环境,您可以使用 explode 将 fgetcsv 函数替换为您自己的函数

    【讨论】:

    • @icewind 这解决了我的问题:现在总是显示文本。但是,我仍然需要手动将浏览器编码从 ISO-8859-1 更改为 UTF-8。你知道为什么我的元标签被忽略了吗?无论您是否回答此问题,您的回答都将被接受。
    • @deceze 你错了。这解决了我不显示文本的问题。不过我也很惊讶:)
    • @deceze 您使用执行数据操作的函数 fgetcsv 阅读。您可以在关于语言环境的注释部分阅读文档about fgetcsv
    • @mkk 尝试在任何输出之前发送标头header('Content-type: text/html; charset=utf-8');
    • 这对我来说仍然没有什么意义,因为 UTF-8 与 ASCII 兼容,fgetcsv 正在寻找的任何“特殊字符”都应该是 ASCII 码点。介于两者之间的任何事情都应该无关紧要。这可能意味着默认语言环境有一些非常奇怪的值,这个值正在修复。
    猜你喜欢
    • 2011-06-13
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 2014-07-24
    相关资源
    最近更新 更多