Ist UTF-16 eine feste Breite oder eine variable Breite? Ich habe unterschiedliche Ergebnisse aus verschiedenen Quellen erhalten:
Von http://www.tbray.org/ongoing/When/200x/2003/04/26/UTF :
UTF-16 speichert Unicode-Zeichen in 16-Bit-Blöcken.
Aus http://en.wikipedia.org/wiki/UTF-16/UCS-2 :
UTF-16 (16-Bit-Unicode-Transformationsformat) ist eine Zeichencodierung für Unicode, mit der 1.112.064 [1] Zahlen (als Codepunkte bezeichnet) im Unicode-Codebereich von 0 bis 0x10FFFF codiert werden können. Es wird ein Ergebnis variabler Länge mit einer oder zwei 16-Bit-Codeeinheiten pro Codepunkt erzeugt.
Aus der ersten Quelle
UTF-8 hat auch den Vorteil, dass die Codierungseinheit das Byte ist, sodass es keine Probleme mit der Byte-Reihenfolge gibt.
Warum hat UTF-8 kein Problem mit der Bytereihenfolge? Es ist variabel und ein Zeichen kann mehr als ein Byte enthalten. Ich denke also, dass die Reihenfolge der Bytes immer noch ein Problem sein kann.
Danke und Grüße!
Antworten:
Sie scheinen zu missverstehen, was Endian-Themen sind. Hier ist eine kurze Zusammenfassung.
Eine 32-Bit-Ganzzahl belegt 4 Bytes. Nun kennen wir die logische Reihenfolge dieser Bytes. Wenn Sie eine 32-Bit-Ganzzahl haben, können Sie das High-Byte mit dem folgenden Code abrufen:
Das ist alles schön und gut. Wo das Problem beginnt, ist, wie verschiedene Hardware ganze Zahlen aus dem Speicher speichert und abruft.
In der Big-Endian-Reihenfolge wird ein 4-Byte-Speicher, den Sie als 32-Bit-Ganzzahl lesen, gelesen, wobei das erste Byte das High-Byte ist:
In Little Endian-Reihenfolge wird ein 4-Byte-Speicher, den Sie als 32-Bit-Ganzzahl lesen, gelesen, wobei das erste Byte das untere Byte ist:
Wenn Sie einen Zeiger auf einen Zeiger auf einen 32-Bit-Wert haben, können Sie dies tun:
Das Ergebnis ist laut C / C ++ undefiniert. Es könnte 0x81 sein. Oder es könnte 0x32 sein. Technisch könnte es alles zurückgeben, aber für echte Systeme wird es das eine oder andere zurückgeben.
Wenn Sie einen Zeiger auf eine Speicheradresse haben, können Sie diese Adresse als 32-Bit-Wert, 16-Bit-Wert oder 8-Bit-Wert lesen. Auf einer Big-Endian-Maschine zeigt der Zeiger auf das High-Byte. Auf einer kleinen Endian-Maschine zeigt der Zeiger auf das niedrige Byte.
Beachten Sie, dass es hier nur um das Lesen und Schreiben in den / aus dem Speicher geht. Es hat nichts mit dem internen C / C ++ - Code zu tun. Die erste Version des Codes, die C / C ++ nicht als undefiniert deklariert, funktioniert immer , um das High-Byte zu erhalten.
Das Problem ist, wenn Sie mit dem Lesen von Byte-Streams beginnen. Wie aus einer Datei.
16-Bit-Werte haben dieselben Probleme wie 32-Bit-Werte. Sie haben nur 2 Bytes anstelle von 4. Daher kann eine Datei 16-Bit-Werte enthalten, die in Big-Endian- oder Little-Endian-Reihenfolge gespeichert sind.
UTF-16 ist als Folge von 16-Bit-Werten definiert . Tatsächlich ist es ein
uint16_t[]
. Jede einzelne Codeeinheit ist ein 16-Bit-Wert. Um UTF-16 korrekt laden zu können, müssen Sie daher die Endianität der Daten kennen.UTF-8 ist als Folge von 8-Bit-Werten definiert . Es ist ein
uint8_t[]
. Jede einzelne Codeeinheit hat eine Größe von 8 Bit: ein einzelnes Byte.Sowohl in UTF-16 als auch in UTF-8 können mehrere Codeeinheiten (16-Bit- oder 8-Bit-Werte) zu einem Unicode-Codepunkt (einem "Zeichen") kombiniert werden, dies ist jedoch nicht der richtige Begriff, sondern eine Vereinfachung ). Die Reihenfolge dieser Codeeinheiten, die einen Codepunkt bilden, wird durch die UTF-16- und UTF-8-Codierungen bestimmt.
Bei der Verarbeitung von UTF-16 lesen Sie einen 16-Bit-Wert und führen die erforderliche Endian-Konvertierung durch. Dann stellen Sie fest, ob es sich um ein Ersatzpaar handelt. Wenn dies der Fall ist, lesen Sie einen weiteren 16-Bit-Wert, kombinieren die beiden und erhalten daraus den Unicode-Codepunktwert.
Bei der Verarbeitung von UTF-8 lesen Sie einen 8-Bit-Wert. Eine Endian-Konvertierung ist nicht möglich, da nur ein Byte vorhanden ist. Wenn das erste Byte eine Multibyte-Sequenz angibt, lesen Sie eine bestimmte Anzahl von Bytes, die von der Multibyte-Sequenz vorgegeben wird. Jedes einzelne Byte ist ein Byte und hat daher keine Endian-Konvertierung. Die Reihenfolge dieser Bytes in der Sequenz wird ebenso wie die Reihenfolge der Ersatzpaare in UTF-16 durch UTF-8 definiert.
Es kann also keine Endian-Probleme mit UTF-8 geben.
quelle
Die Antwort von Jeremy Banks ist zwar richtig, hat aber die Bytereihenfolge nicht berücksichtigt.
Wenn Sie UTF-16 verwenden, werden die meisten Glyphen mit einem Zwei-Byte-Wort gespeichert. Wenn das Wort jedoch in einer Festplattendatei gespeichert wird, in welcher Reihenfolge speichern Sie die einzelnen Bytes?
Das CJK-Zeichen (Chinesisch) für das Wort "Wasser" hat beispielsweise eine UTF-16-Codierung in hexadezimaler Schreibweise von 6C34. Wenn Sie das als zwei Bytes auf die Festplatte schreiben, schreiben Sie es als "Big-Endian" (die zwei Bytes sind 6C 34)? Oder schreiben Sie es als "Little-Endian" (die beiden Bytes sind 34 6C)?
Bei UTF-16 sind beide Ordnungen legitim, und Sie geben normalerweise an, welche die Datei hat, indem Sie das erste Wort in der Datei zu einer Byte Order Mark (BOM) machen, die für die Big-Endian-Codierung FE FF und für Little-Endian ist Kodierung ist FF FE.
UTF-32 hat das gleiche Problem und die gleiche Lösung.
UTF-8 hat dieses Problem nicht, weil es eine variable Länge hat und Sie effektiv die Byte-Sequenz eines Glyphen schreiben, als ob es ein Little-Endian wäre. Beispielsweise wird der Buchstabe "P" immer mit einem Byte codiert - 80 - und das Ersatzzeichen wird immer mit den zwei Bytes FF FD in dieser Reihenfolge codiert.
Einige Programme setzen einen Drei-Byte-Indikator (EF BB BF) am Anfang einer UTF-8-Datei. Dies hilft dabei, UTF-8 von ähnlichen Kodierungen wie ASCII zu unterscheiden. Dies kommt jedoch nur unter MS Windows häufig vor.
quelle