【问题标题】:How come that two identically encoded words look different in htmlentities?为什么两个相同编码的单词在 htmlentities 中看起来不同?
【发布时间】:2012-12-15 21:29:09
【问题描述】:

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

【问题讨论】:

  • 这两个变量是如何分配的?
  • 其中一个存储在一个数组中,该数组通过会话传递(在另一个文件中创建),另一个由 curl 获取并存储在一个数组中。
  • 你能发布在这两个变量上调用urlencode 的结果吗?这将向我们展示实际存在的字节数。
  • 这是一个例子:%CE%B1%CF%85%CF%84%CE%BF%CE%BA%CE%AF%CE%BD%CE%B7%CF%84%CE%BF(第一个变量),%26alpha%3B%26upsilon%3B%26tau%3B%26omicron%3B%26kappa%3B%26%23943%3B%26nu%3B%26eta%3B%26tau%3B%26omicron%3B(第二个变量)

标签: php encoding utf-8


【解决方案1】:

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

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

Web 浏览器和一些过于友好的“所见即所得”编辑器会将这些字符串呈现为相同,但实际字符串的二进制表示(计算机将比较)是不同的。这就是为什么相等测试失败的原因,即使在浏览器或编辑器中进行人类视觉检查时字符串看起来是相同的。

我认为在这种情况下您不能依靠 mb_detect_encoding 来检测编码,因为无法使用 CER 表示非 ASCII 来区分 utf-8 和 ASCII。

您的第二个问题是:我该如何解决这个问题?

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

我的解决方法如下:我实现了一个名为 utf8_normalize 的便捷函数,它可以转换几乎所有常见的字符表示(在我的例子中:CER、NER、iso-8859-1 和 CP-1252) canonical utf-8 在比较字符串之前。您在其中输入的内容在某种程度上必须取决于您的软件将运行的环境类型中的“流行”字符表示形式,但如果您在比较之前确保您的字符串采用规范形式,它将起作用。

正如下面来自 OP (phpheini) 的评论中所指出的,还存在 PHP Normalizer class,它可能比本土函数做得更好。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-05
  • 2019-08-31
  • 1970-01-01
  • 1970-01-01
  • 2021-02-13
  • 2017-07-31
相关资源
最近更新 更多