在函数mb_detect_encoding中有严格模式的参数。PHP函数mb_detect_encoding严格模式
在第一个,最upvoted评论:
<?php
$str = 'áéóú'; // ISO-8859-1
mb_detect_encoding($str, 'UTF-8'); // 'UTF-8'
mb_detect_encoding($str, 'UTF-8', true); // false
这是真实的,是的。但有谁能给我一个解释,为什么?
在函数mb_detect_encoding中有严格模式的参数。PHP函数mb_detect_encoding严格模式
在第一个,最upvoted评论:
<?php
$str = 'áéóú'; // ISO-8859-1
mb_detect_encoding($str, 'UTF-8'); // 'UTF-8'
mb_detect_encoding($str, 'UTF-8', true); // false
这是真实的,是的。但有谁能给我一个解释,为什么?
我没有写它,我没有用调试器来完成它,这只是我的解释而已。
看来,意图是严格模式,并检查字符串作为一个整体是有效的编码,而非严格的模式将允许子序列能成为其中的一部分有效的字符串。例如,如果字符串以多字节字符的第一个字节结尾,则它在严格模式下不会匹配,但在非严格模式下仍可以使用UTF-8。
但是,似乎有一个错误*在非严格模式下,只有字符串的第一个字节在某些情况下被检查。
实施例:
字节0xf8
不以UTF-8的任何位置允许的。当放置在字符串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()
错误地返回字符串因为这样可能会发生。
因为$str
不是实际的UTF-8
,而是ISO-8859-1
。由于当不严格比较,UTF-8
可以被处理相同ISO-8859-1
,但使用严格模式时仅实际UTF-8
适合用于UTF-8
比较(explained here)
这些特定的字符在UTF-8和8859中看起来非常不同。它们肯定不是“相同”,不能被“对待相同”。这仅适用于前128个字符(ASCII),这些不属于这些字符。该字符串在UTF-8期间明显无效。 – deceze
在ISO-8859-1编码áéóú
为:
e1 e9 f3 fa
如果你误解为UTF-8,你只会得到四个无效的字节序列。多字节扩展基本上被设计为忽略错误。例如,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()
是一般不像你的东西是有用的,它是使用默认参数总废话。
不管是笑还是哭,这就是问题所在。 – deceze
最终该标志被穿过,以[这里](https://github.com/php/php-src/blob/打开这个报告c72282a13b12b7e572469eba7a7ce593d900a8a2/EXT/MBSTRING/libmbfl/mbfl/mbfilter.c#L718);但如果我能弄清楚它的功能,我会受到诅咒...... – deceze
FWIW,*另一个原因是从来没有使用过这个功能,因为*检测*编码从根本上说是不可能的。非常有趣的问题。 – deceze
@deceze滑稽:关于整个源代码中'strict'的唯一评论是'/ * set strict flag * /' –