2011-07-17 25 views
18

的iconv功能有時給我一個錯誤:如何在PHP中檢測格式錯誤的utf-8字符串?

Notice: 
iconv() [function.iconv]: 
Detected an incomplete multibyte character in input string in [...] 

有沒有一種方法來檢測,有以UTF-8串非法字符將數據inconv過嗎?

+0

同時,我發現這一點:HTTP:// stackoverflow.com/questions/4407854/how-to-detect-if-have-to-apply-utf8-decode-or-encode-on-a-string – rsk82

回答

46

首先,請注意,無法檢測文本是否屬於特定的不需要的編碼。您只能檢查給定編碼中的字符串是否有效。

自PHP 4.3.5以來,您可以使用preg_match[PHP Manual]中提供的UTF-8有效性檢查。它會返回0(無附加信息),如果一個無效的字符串給出:

$isUTF8 = preg_match('//u', $string); 

另一種可能性是mb_check_encoding[PHP Manual]

$validUTF8 = mb_check_encoding($string, 'UTF-8'); 

您可以使用的另一個功能是mb_detect_encoding[PHP Manual]

$validUTF8 = ! (false === mb_detect_encoding($string, 'UTF-8', true)); 

將參數strict設置爲true非常重要。

此外,iconv[PHP Manual]允許您即時更改/刪除無效序列。 (但是,如果iconv遇到這樣的序列,它會生成一個通知,這種行爲不能被改變。)

echo 'TRANSLIT : ', iconv("UTF-8", "ISO-8859-1//TRANSLIT", $string), PHP_EOL; 
echo 'IGNORE : ', iconv("UTF-8", "ISO-8859-1//IGNORE", $string), PHP_EOL; 

您可以使用@並檢查返回字符串的長度:

strlen($string) === strlen(@iconv('UTF-8', 'UTF-8//IGNORE', $string)); 

檢查手冊頁上的示例也在iconv中。

您尚未分享通知所源自的源代碼。如果你想要更具體的建議,你應該添加它。

+0

你沒有錯,但似乎'preg_match('!。!u',$ str)'做了技巧 - 在嘗試查找任何內容之前,它會靜靜地檢查str是否爲utf-8。 - 正則表達式中的那個點甚至不需要 – rsk82

+0

@ user393087:我做了一個輕微的編輯,以使'preg_match'方法在空字符串上正常工作。 – hakre

+2

@Alan:感謝您的好編輯。 – hakre

0

UTF-8中無效字符的規範非常清晰。在試圖解析它之前,您可能想要將它們除去。他們不應該在那裏,所以如果你能夠避免它,甚至在生成更好的XML之前。

在這裏看到一個參考:

http://www.w3.org/TR/xml/#charsets

這不是一個完整列表,許多解析器還禁止一些低編號的控制字符,但現在我不能找到一個完整列表。

然而,的iconv可能有此內置支持:

http://www.zeitoun.net/articles/clear-invalid-utf8/start

0

你可以嘗試使用mb_detect_encoding檢測,如果你有一個不同的字符集(比UTF-8),然後mb_convert_encoding轉換爲UTF-8(如果需要)。人們更有可能以不同的字符集爲您提供有效的內容,而不是給您無效的UTF-8。

+0

請注意,有效的ASCII字符串也是有效的UTF8字符串。這意味着mb_detect_encoding將爲任何字符串返回「ASCII」,這是一個有效的UTF8字符串,並且不包含任何Unicode字符。 – GordonM

0

把一個@中的iconv的前面()來抑制注意和// IGNORE UTF-8在源編碼ID後忽略無效字符:

@iconv('UTF-8//IGNORE', $destinationEncoding, $yourString); 
+0

我知道如何忽略它,我不知道如何檢測它,我不想將它默默地傳遞給我的代碼。 – rsk82

+0

檢測到錯誤後你想要做什麼? – nobody

+0

順便說一句,在另一個問題'preg_match()'解決方案是非常有趣的,我會去那。 – nobody