2016-06-30 5 views
0

Mein PHP-Skript empfängt externe JSON-Daten von woanders; Leider, irgendwo auf dem Weg, diese Daten erhalten seine UTF-8-Zeichen beschädigt.(Re) Konvertierung von korrupten UTF-8-Eingabe in PHP?

Zum Beispiel sollte ich die Zeichenfolge "40.80 – Origin:" erhalten, aber stattdessen bekomme ich etwas wie "40.80 â Origin:". Inspizieren diese um den korrupten Saibling mit hexdump und utfinfo.pl, erhalte ich:

$ 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.| 

Also, im Grunde die UTF-8-Byte-Sequenz für en-dash, 0xE2,0x80,0x93, bekam irgendwie geändert 0xC3,0xA2 0xC2, 0x80 0xC2,0x93. (Scheinbar könnte ich nur die 0xC2 für die zweiten beiden loswerden, aber ich kann nicht sehen, wie ich 0xC3,0xA2 für das erste Byte zurück in 0xE2 transformieren könnte).

Anyways, ich dachte, dass ich in Funktionen gebaut einige von PHP nutzen könnten zurück in UTF-8 zurückzuverwandeln, so schrieb ich dieses kleine Testskript, 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"; 

?> 

... leider, es doesn‘ t Arbeit - das ist der Ausgang I in Terminal erhalten, wenn es über pHP-CLI ausgeführt wird:

$ 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: 

... das heißt, ich korrupt alles noch mehr. (Beachten Sie, dass die mb_detect_encoding diese Zeichenfolge aus irgendeinem Grund als UTF-8 erkennt).

Also, wie kann ich diese Zeichenfolge zurück in die richtige UTF-8 konvertieren?

BEARBEITEN: (un) zum Glück, SO wurde los von den schlechten Zeichen, so dass Sie nicht in der Lage sein werden, dieses Beispiel nur durch Kopieren kopieren :(, aber hoffentlich die Hexdumps bieten genug Informationen?! Wenn nicht, reposted ich die oben auf einem Github Gist, die in der rohen Ausgabe die Zeichen zu bewahren scheint ...

+1

Wie erhalten Sie die JSON-Daten, was ist Ihre akzeptierte Codierung? – postrel

+0

@postrel - die akzeptierte Codierung ist UTF-8, ich erhalte es über Casperjs von einer Webseite (nicht öffentlich), die es sonst als UTF-8 deklariert, so dass ich wirklich nicht verstehe, warum die Korruption überhaupt auftritt; Leider kann ich ein Beispiel nicht rekonstruieren, um dies in casperjs zu demonstrieren, und bin daher gezwungen, dies in PHP zu korrigieren, wenn überhaupt möglich ... – sdbbs

+1

'echo" â O "' auf der CLI ist eine schlechte Möglichkeit, die Codierung zu testen, gibt es So eine komplexe Kette von Entschlüsselung und Kodierung passiert in dieser Kopie-von-Quelle-Paste-zu-Terminal-interpretieren-durch-CLI, dass es unmöglich ist zu sagen, ob das Ergebnis irgendetwas bedeutet. Dasselbe gilt für Ihr PHP-Testskript. Sie müssen die Quelle direkt hexen. – deceze

Antwort

0

Ich glaube, ich habe es, dank Convert utf8-characters to iso-88591 and back in PHP:

utf8_decode - Wandelt einen String mit ISO-8859-1 Zeichen mit UTF-8 kodiert Single-Byte-ISO-8859-1

Also habe ich versucht, um das Skript hinzufügen:

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

... und dies druckt 40.80 – Origin: wie es sollte.