簡體   English   中英

(重新)在PHP中轉換損壞的UTF-8輸入?

[英](Re)converting corrupt UTF-8 input in PHP?

我的PHP腳本從其他地方接收外部JSON數據; 不幸的是,在此過程中,此數據的UTF-8字符已損壞。

例如,我應該收到字符串“ 40.80 – Origin: ”,但是我得到的卻是“ 40.80 â Origin: ”。 使用hexdumputfinfo.pl在損壞的char周圍檢查這些,我得到:

$ echo " – O" | perl utfinfo.pl 
Got 4 uchars
Char: ' ' u: 32 [0x0020] b: 32 [0x20] n: SPACE [Basic Latin]
Char: '–' u: 8211 [0x2013] b: 226,128,147 [0xE2,0x80,0x93] n: EN DASH [General Punctuation]
Char: ' ' u: 32 [0x0020] b: 32 [0x20] n: SPACE [Basic Latin]
Char: 'O' u: 79 [0x004F] b: 79 [0x4F] n: LATIN CAPITAL LETTER O [Basic Latin]

$ echo " – O" | hexdump -C
00000000  20 e2 80 93 20 4f 0a                              | ... O.|

$ echo " â O" | perl utfinfo.pl 
Got 6 uchars
Char: ' ' u: 32 [0x0020] b: 32 [0x20] n: SPACE [Basic Latin]
Char: 'â' u: 226 [0x00E2] b: 195,162 [0xC3,0xA2] n: LATIN SMALL LETTER A WITH CIRCUMFLEX [Latin-1 Supplement]
Char: '' u: 128 [0x0080] b: 194,128 [0xC2,0x80] n: <control> [Latin-1 Supplement]
Char: '' u: 147 [0x0093] b: 194,147 [0xC2,0x93] n: <control> [Latin-1 Supplement]
Char: ' ' u: 32 [0x0020] b: 32 [0x20] n: SPACE [Basic Latin]
Char: 'O' u: 79 [0x004F] b: 79 [0x4F] n: LATIN CAPITAL LETTER O [Basic Latin]

$ echo " â O" | hexdump -C
00000000  20 c3 a2 c2 80 c2 93 20  4f 0a                    | ...... O.|

因此,基本上是破折號的0xE2,0x80,0x93的UTF-8字節序列,以某種方式變為0xC3,0xA2 0xC2,0x80 0xC2,0x93。 (看似,我可以擺脫后兩個的0xC2,但看不到如何將第一個字節的0xC3,0xA2轉換回0xE2)。

無論如何,我認為我可以使用PHP的一些內置函數將其轉換回UTF-8,因此我編寫了這個小測試腳本test_utf8.php

<?php
# 40.80  – Origin:
$tstr = "40.80  â Origin:";
echo "$tstr\n";
print(mb_detect_encoding ($tstr) . "\n"); // UTF-8 here

$tstrB = mb_convert_encoding($tstr, "UTF-8");
echo "$tstrB\n";

$tstrC = iconv('ASCII', 'UTF-8//IGNORE', $tstr);
echo "$tstrC\n";

$tstrD = utf8_encode($tstr);
echo "$tstrD\n";

?>

...不幸的是,它不起作用-這是我通過php CLI運行它時在終端中得到的輸出:

$ php test_utf8.php
40.80  â Origin:
UTF-8
40.80  â Origin:
PHP Notice:  iconv(): Detected an illegal character in input string in /path/to/test_utf8.php on line 10

40.80  â Origin:

……也就是說,我更加破壞了一切。 (請注意,出於某種原因, mb_detect_encoding將此字符串檢測為UTF-8)。

那么,如何重新將此字符串轉換回正確的UTF-8?

編輯:(不幸的),所以擺脫了壞字符,所以您將無法僅通過復制粘貼來重構此示例:( ,但希望hexdumps提供了足夠的信息?!如果沒有,我將以上內容重新發布到了Github Gist ,在原始版本中似乎保留了角色...

我想我明白了,這要歸功於將utf8-字符轉換為iso-88591並返回到PHP中

utf8_decode —將使用UTF-8編碼的ISO-8859-1字符的字符串轉換為單字節ISO-8859-1

因此,我嘗試添加到腳本中:

$tstrF = utf8_decode($tstr);
echo "$tstrF\n";

...,這會打印出40.80 – Origin:應該的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM