即使设置了UTF-8编码,在浏览器中显示俄语字母也有问题

时间:2011-08-23 14:24:25

标签: php unicode utf-8 character-encoding

我知道有一些类似的问题。然而,在阅读了答案并对该主题进行了讨论之后,我仍在努力在浏览器中显示俄语字母。我将它们存储在.csv文件中(以UTF-8编码,没有BOM)。在我的php文件中读取.csv(也是以UTF-8编码无BOM)我声明了charset:

 <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];
        }
     }

(我省略第一列并显示第二列的内容,它总是被填充)

2 个答案:

答案 0 :(得分:5)

检查您的服务器配置

您是否已将Apache配置为遵守<meta>字符集覆盖?默认情况下,它使用ISO-8859-1作为其默认,并忽略在其提供的网页中出现的任何替代。

解决方案#1 of 3

例如,您可以将其放在.htaccess文件中作为封闭目录,现在您的网页将会<meta>覆盖其荣誉:

AddDefaultCharset Off
AddCharset UTF-8 .html

Apache documentation州:

  

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

iso-8859-1
     

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

在我关闭AddDefaultCharset之前,我无法使AddDefaultCharset代码生效。这是非常神秘和令人沮丧的。但是,一旦我这样做,一切都顺利进行。

解决方案#2 of 3

如果您具有对Apache配置文件的写入权限,则可以更改服务器本身。但是,您必须确保没有其他任何内容依赖于旧的不可重写设置。这是使用<meta>的另一个原因。


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

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

.htaccess

你必须改为使用

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

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

这样做的好处是它不再需要&#x426;&#x435;&#x43B;&#x43B;&#x44C;-&#x430;&#x43C;-&#x417;&#x435;&#x435; 覆盖和摆弄服务器或使用<meta>文件。缺点是它需要额外的翻译通道,这会干扰能够使用理解文字UTF-8的编辑器直接编辑文件。

实体忽略编码

它起作用的原因是因为所有HTML始终使用Unicode,因此字符编号1062始终为.htaccess等。实体编号始终表示Unicode代码点编号;它们永远不是文档编码中的数字。只有编码的字节计为服务器或页面编码,而不是编码的始终为Unicode的未编码的代码点。

这就是为什么我们可以使用类似CYRILLIC CAPITAL LETTER TSE的内容而始终意味着 &#233;,因为代码点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,LATIN SMALL LETTER E WITH ACUTE,作为字符实体,您将使用CYRILLIC CAPITAL LETTER TSE&#1062; - 而不是&#x426;,因为U + 00C6为&#xC6;,这将是错误的。

同样,如果您使用的是MacCyrillic编码,则字面值为0x96的字节为LATIN CAPITAL LETTER AE,但由于数字实体始终使用Unicode,因此您必须使用CYRILLIC CAPITAL LETTER TSE&#1062; - 而不是&#x426;

我更喜欢在所有网页上只使用UTF-8。嗯,对于新的,那就是。我确实认识到存在遗留的非Unicode页面。我刚刚离开的那些人。

答案 1 :(得分:4)

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

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函数