PHP函数mb_detect_encoding严格模式

时间:2016-08-24 07:39:39

标签: php character-encoding

在函数mb_detect_encoding中有一个严格模式的参数。

在第一个最受欢迎的评论中:

<?php
$str = 'áéóú'; // ISO-8859-1
mb_detect_encoding($str, 'UTF-8'); // 'UTF-8'
mb_detect_encoding($str, 'UTF-8', true); // false

这是真的,是的。但有人可以给我一个解释,为什么呢?

3 个答案:

答案 0 :(得分:4)

此答案中的所有内容均基于我对代码herehere的阅读。

我没有写它,我没有用调试器单步执行它,这只是我的解释。

似乎意图用于严格模式来检查整个字符串是否对编码有效,而非严格模式允许可以的子序列是一个有效字符串的一部分。例如,如果字符串以多字节字符的第一个字节结束,它在严格模式下不匹配但在非严格条件下仍然符合UTF-8的条件模式。

然而似乎有一个错误*在非严格模式下,在某些情况下只检查字符串的第一个字节。

示例:

UTF-8中不允许使用字节0xf8。当放置在字符串mb_detect_encoding()的开头时,无论使用哪种模式,都会正确地返回false。

$str = "\xf8foo";

var_dump(
    mb_detect_encoding($str, 'UTF-8'),      // bool(false)
    mb_detect_encoding($str, 'UTF-8', true) // bool(false)
);

但只要前导字节可能出现在UTF-8序列中的任何地方,非严格模式就会返回UTF-8。

$str = "foo\xf8";

var_dump(
    mb_detect_encoding($str, 'UTF-8'),      // string(5) "UTF-8"
    mb_detect_encoding($str, 'UTF-8', true) // bool(false)
);

因此,当您的ISO-8859-1字符串'áéóú'无效UTF-8时,第一个字节"\xe1"可能出现在UTF-8中,mb_detect_encoding()错误地返回字符串,因此

* 我在https://bugs.php.net/bug.php?id=72933

打开了一份报告

答案 1 :(得分:2)

ISO-8859-1中的

áéóú编码为:

e1 e9 f3 fa

如果您将其误解为UTF-8,则只会获得四个无效字节序列。 Multi-Byte扩展基本上是为忽略错误而设计的。例如,mb_convert_encoding()会将这些序列替换为question marks或您使用mb_substitute_character()设置的任何内容。

我有根据的猜测是严格的编码决定了无效字节序列应该做什么:

  • false表示删除它们
  • true意味着保留他们

如果您忽略这些无效序列,您显然会丢弃极有价值的信息,而您只能在非常有限的情况下获得明智的结果,例如

$str = chr(81);
var_dump( mb_detect_encoding($str, ['ISO-8859-1', 'Windows-1252']) );
var_dump( mb_detect_encoding($str, ['Windows-1252', 'ISO-8859-1']) );

总而言之,mb_detect_encoding()通常不会像您那样有用,而且它与默认参数的总垃圾一样。

答案 2 :(得分:-2)

因为$str不是实际UTF-8,而是ISO-8859-1。由于未进行严格比较,UTF-8可能与ISO-8859-1相同,但在使用严格模式时,只有实际UTF-8适合UTF-8比较(explained here)< / p>