2016-08-24 101 views
6

在函數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 

這是真實的,是的。但有誰能給我一個解釋,爲什麼?

+1

最終該標誌被穿過,以[這裏](https://github.com/php/php-src/blob/打開這個報告c72282a13b12b7e572469eba7a7ce593d900a8a2/EXT/MBSTRING/libmbfl/mbfl/mbfilter.c#L718);但如果我能弄清楚它的功能,我會受到詛咒...... – deceze

+0

FWIW,*另一個原因是從來沒有使用過這個功能,因爲*檢測*編碼從根本上說是不可能的。非常有趣的問題。 – deceze

+0

@deceze滑稽:關於整個源代碼中'strict'的唯一評論是'/ * set strict flag * /' –

回答

4

本答案中的所有內容都基於我對代碼herehere的閱讀。

我沒有寫它,我沒有用調試器來完成它,這只是我的解釋而已。


看來,意圖是嚴格模式,並檢查字符串作爲一個整體是有效的編碼,而非嚴格的模式將允許子序列能成爲其中的一部分有效的字符串。例如,如果字符串以多字節字符的第一個字節結尾,則它在嚴格模式下不會匹配,但在非嚴格模式下仍可以使用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()錯誤地返回字符串因爲這樣可能會發生。


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

-2

因爲$str不是實際的UTF-8,而是ISO-8859-1。由於當不嚴格比較,UTF-8可以被處理相同ISO-8859-1,但使用嚴格模式時僅實際UTF-8適合用於UTF-8比較(explained here

+1

這些特定的字符在UTF-8和8859中看起來非常不同。它們肯定不是「相同」,不能被「對待相同」。這僅適用於前128個字符(ASCII),這些不屬於這些字符。該字符串在UTF-8期間明顯無效。 – deceze

2

在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()是一般不像你的東西是有用的,它是使用默認參數總廢話。

+0

不管是笑還是哭,這就是問題所在。 – deceze