2016-04-19 11 views
1

Ich habe Schwierigkeiten, die Zeichencodierung in PHP zu verstehen.Grundlegende Zeichencodierung in PHP

Betrachten Sie das folgende Skript (Sie es here laufen kann):

$string = "\xe2\x82\xac"; 

var_dump(mb_internal_encoding()); 
var_dump($string); 
var_dump(unpack('C*', $string)); 
$utf8string = mb_convert_encoding($string, "UTF-8"); 
var_dump($utf8string); 
var_dump(unpack('C*', $utf8string)); 

mb_internal_encoding("UTF-8"); 

var_dump($string); 
var_dump($utf8string); 

Ich habe eine Zeichenfolge, tatsächlich das € Zeichen mit seinen Unicode-Codepunkte dargestellt. Bis zu PHP 5.5 ist die verwendete interne Kodierung ISO-8859-1, daher denke ich, dass meine Zeichenfolge mit dieser Kodierung kodiert wird. Mit unpack kann ich die Bissrepräsentation meiner Zeichenfolge sehen, und es entspricht den hexadezimalen Codes, die ich benutze, um die Zeichenfolge zu definieren.

Dann konvertiere ich die Codierung der Zeichenfolge zu UTF-8, mit mb_convert_encoding. Zu diesem Zeitpunkt wird die Zeichenfolge auf dem Bildschirm anders angezeigt und ihre Byte-Darstellung ändert sich (und dies wird erwartet). Wenn ich die PHP interne Codierung auch in UTF-8 ändere, würde ich erwarten, dass utf8string korrekt auf dem Bildschirm angezeigt wird, aber das passiert nicht.

Was ich vermisse?

+1

Führen Sie dies in einem Browser aus?Das wird seine eigene Entscheidung über die Zeichencodierung treffen, und Sie wären besser dran, wenn die Entität den beleidigenden Charakter verlassen würde. – Chris

+0

Fügen Sie ein '' zu dem '' hinzu, um sicherzustellen, dass der Browser auch UTF8 erwartet. – RiggsFolly

+0

Alle Strings in PHP werden als binäre Strings behandelt, und 'mb_internal_encoding()' betrifft buchstäblich nichts anderes als wie andere 'mb_ *' Funktionen funktionieren. Sie können auch nicht sowohl ISO-8859 als auch UTF8 im selben Dokument ausgeben und erwarten, dass alles passiert, unabhängig davon, welches Programm die Ausgabe erzeugt. – Sammitch

Antwort

2

Das angezeigte Skript verwendet keine nicht-ASCII-Zeichen, so dass die interne Kodierung keinen Unterschied macht. mb_internal_encoding konvertiert Ihre Daten bei der Ausgabe. This question wird Ihnen mehr darüber erzählen, wie es funktioniert; es wird dir auch sagen, dass es besser ist, es nicht zu benutzen.

Die Drei-Byte-Zeichenfolge $string in Ihrem Code ist die UTF-8-Darstellung des Euro-Symbols, nicht dessen "Unicode-Codepunkt" (der wie alle gängigen Unicode-Zeichen 2 Byte breit ist: 0x20ac).

Bereinigt dies das Verhalten, das Sie sehen?

1

Sie haben mit einer Zeichenfolge begonnen, die die utf-8 Darstellung des Euro-Symbols darstellt. Wenn Sie echo($string) ausführen, erzeugen alle Versionen von PHP die drei Bytes, die Sie in $string setzen. Wie sie vom Browser interpretiert werden, hängt von dem im Header Content-Type angegebenen Zeichensatz ab. Wenn es text/html; charset=utf-8 ist, dann erhalten Sie das Euro-Zeichen in der gerenderten Seite.

Dann machen Sie den falschen Zug. Sie rufen mb_convert_encoding() mit nur zwei Argumenten auf. Dadurch kann PHP den aktuellen Wert seiner internen Codierung verwenden, die von der Erweiterung mb_string für das dritte Argument verwendet wird ($from_encoding). Warum?

Für PHP 5.6 und neuer ist der Standardwert von mb_internal_encoding()utf-8 und der Aufruf an mb_convert_encoding() ist ein No-Op.

Aber für frühere Versionen von PHP ist der Standardwert, der von mb_internal_encoding() zurückgegeben wird, iso-8859-1 und es stimmt nicht mit der Codierung Ihrer Zeichenfolge überein. Dementsprechend interpretiert mb_convert_encoding() die Bytes $string als drei einzelne Zeichen und codiert sie mit den Regeln utf-8. Das Ergebnis ist offensichtlich falsch.

Btw, wenn Sie $string mit '€' initialisieren, erhalten Sie die gleiche Ausgabe auf allen PHP-Versionen (sogar auf PHP 4, Iirc).