在函數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 * /' –