为什么两个相同编码的单词在htmlentities中看起来不一样?

时间:2012-12-15 21:29:09

标签: php encoding utf-8

我有一个关于UTF-8和htmlentities的问题。我有两个带有希腊文字的变量,它们似乎都是UTF-8编码的(根据mb_detect_encoding())。当我输出两个变量时,它们在浏览器中看起来完全相同(也在源代码中)。 当我意识到,一个简单的if($var1 == $var2)总是失败,我感到很惊讶,尽管它们看起来完全相同。所以我使用htmlentities来查看html代码是否相同。当我看到第一个变量看起来像这样时我很惊讶:Ï�κÏ�λοÏ�而另一个变量是这样的:ια&ro;。怎么可能两个具有相同编码的相同单词(UTF-8)仍然不同?我怎么能解决这个问题?

1 个答案:

答案 0 :(得分:3)

你的第一个问题是:两个具有相同编码(UTF-8)的相同单词怎么会有所不同呢?

在这种情况下,两种情况下编码都不是真正的UTF-8。第一个变量是“真实的”UTF-8,而在第二个变量中,希腊字符实际上不是UTF-8,而是ASCII,非ASCII字符(希腊语)使用称为CER(字符实体参考)的东西编码

Web浏览器和一些太友好的“WYSIWYG”编辑器会将这些字符串呈现为相同,但实际字符串的二进制表示形式(计算机将比较它们)是不同的。这就是同等测试失败的原因,即使字符串出现在浏览器或编辑器中进行人类视觉检测时也是如此。

在这种情况下,我认为你不能依赖mb_detect_encoding来检测编码,因为除了使用CER来表示非ASCII之外,没有办法告诉utf-8。

你的第二个问题是:我怎么能解决这个问题?

在比较可能以不同方式编码的字符串之前,您需要将它们转换为规范格式(Wikipedia: Canonicalization),以便它们的二进制表示形式完全相同。

以下是我如何解决它:我已经实现了一个名为utf8_normalize的便捷函数,它可以转换任何常见的字符表示形式(在我的例子中:CER,NER,iso-8859-1和CP- 1252)在比较字符串之前, canonical utf-8。你在那里投入的东西必须在某种程度上取决于你的软件将要运行的环境类型中的“流行”字符表示,但如果你只是确保你的字符串在比较之前是规范形式,它将起作用。

如下面OP的评论( phpheini )所述,还存在PHP Normalizer class,它可以更好地实现本土化功能的标准化。