我有一个关于 UTF-8 和 htmlentities 的问题。我有两个带有希腊文本的变量,它们似乎都是 UTF-8 编码的(根据 mb_detect_encoding())。当我输出这两个变量时,它们在浏览器中(也在源代码中)看起来完全一样。
当我意识到一个简单的 if($var1 == $var2)
总是失败时,我感到很惊讶,尽管它们看起来完全一样。所以我用htmlentities看html代码会不会一样。当我看到第一个变量看起来像这样时,我很惊讶:Ï�Ï�Ï�Ï¿Ï�
而另一个像这样:ια&ro;
。具有相同编码 (UTF-8) 的两个相同单词怎么可能仍然不同呢?我该如何解决这个问题?
最佳答案
您的第一个问题是:具有相同编码 (UTF-8) 的两个相同单词怎么可能仍然不同?
在这种情况下,两种情况下的编码都不是真正的 UTF-8。第一个变量是“真正的”UTF-8,而在第二个变量中,希腊字符并不是真正的 UTF-8,而是 ASCII,非 ASCII 字符(希腊语)使用称为 CER(字符实体引用)的东西编码.
Web 浏览器和一些过于友好的“所见即所得”编辑器会将这些字符串呈现为相同,但实际字符串的二进制表示(这是计算机将比较的内容)是不同的。这就是相等测试失败的原因,即使字符串看起来在浏览器或编辑器中的人类视觉检查中是相同的。
我认为在这种情况下您不能依赖 mb_detect_encoding
来检测编码,因为没有办法区分 utf-8 和使用 CER 表示非 ASCII 的 ASCII。
您的第二个问题是:我该如何解决这个问题?
在比较可能编码不同的字符串之前,您需要将它们转换为规范形式 (Wikipedia: Canonicalization),以便它们的二进制表示相同。
这是我解决它的方法:我实现了一个名为 utf8_normalize
的方便函数,它可以转换任何常见字符表示(在我的例子中:CER、NER、iso-8859-1和 CP-1252) 转换为 canonical utf-8,然后再比较字符串。您在其中输入的内容在某种程度上必须取决于您的软件将运行的环境类型中的“流行”字符表示形式,但是如果您只是确保您的字符串在比较之前处于规范形式,它就会起作用。
正如 OP (phpheini) 在下面的评论中指出的那样,还存在 PHP Normalizer class ,这可能比本土函数在规范化方面做得更好。
关于php - 为什么两个相同编码的词在 htmlentities 中看起来不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13896382/