Unterschied zwischen UTF-8 und UTF-16?

137

Unterschied zwischen UTF-8 und UTF-16? Warum brauchen wir diese?

MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();
theJava
quelle
2
Jon Skeet hat einen guten Artikel über Codierung .... csharpindepth.com/Articles/General/Unicode.aspx
Mitch Wheat

Antworten:

283

Ich glaube, es gibt viele gute Artikel darüber im Web, aber hier ist eine kurze Zusammenfassung.

Sowohl UTF-8 als auch UTF-16 sind Codierungen mit variabler Länge. In UTF-8 kann ein Zeichen jedoch mindestens 8 Bit belegen, während in UTF-16 die Zeichenlänge mit 16 Bit beginnt.

Hauptprofis von UTF-8:

  • Grundlegende ASCII-Zeichen wie Ziffern, lateinische Zeichen ohne Akzente usw. belegen ein Byte, das mit der US-ASCII-Darstellung identisch ist. Auf diese Weise werden alle US-ASCII-Zeichenfolgen zu gültigen UTF-8-Zeichenfolgen, die in vielen Fällen eine angemessene Abwärtskompatibilität bieten.
  • Keine Null-Bytes, die die Verwendung von nullterminierten Zeichenfolgen ermöglichen. Dies führt auch zu einer hohen Abwärtskompatibilität.
  • UTF-8 ist unabhängig von der Bytereihenfolge, sodass Sie sich keine Gedanken über das Big Endian / Little Endian-Problem machen müssen.

Haupt-UTF-8-Nachteile:

  • Viele gebräuchliche Zeichen haben unterschiedliche Längen, was die Indizierung nach Codepunkten und die Berechnung einer Codepunktzahl erheblich verlangsamt.
  • Auch wenn die Bytereihenfolge keine Rolle spielt, verfügt UTF-8 manchmal immer noch über eine Stückliste (Byte Order Mark), die darüber informiert, dass der Text in UTF-8 codiert ist, und die Kompatibilität mit der ASCII-Software unterbricht, selbst wenn der Text nur ASCII-Zeichen enthält . Microsoft-Software (wie Notepad) fügt UTF-8 besonders gerne Stücklisten hinzu.

Hauptprofis von UTF-16:

  • BMP-Zeichen (Basic Multilingual Plane), einschließlich Latein, Kyrillisch, die meisten Chinesen (die VR China hat die Unterstützung einiger Codepunkte außerhalb von BMP vorgeschrieben), die meisten Japaner können mit 2 Bytes dargestellt werden. Dies beschleunigt die Indizierung und die Berechnung bei Codepoint Zählung der Text nicht nicht enthalten zusätzliche Zeichen.
  • Selbst wenn der Text zusätzliche Zeichen enthält, werden diese immer noch durch Paare von 16-Bit-Werten dargestellt. Dies bedeutet, dass die Gesamtlänge immer noch durch zwei teilbar ist und die Verwendung von 16-Bit charals primitive Komponente der Zeichenfolge ermöglicht.

Haupt-UTF-16-Nachteile:

  • Viele Null-Bytes in US-ASCII-Zeichenfolgen, dh keine nullterminierten Zeichenfolgen und viel verschwendeter Speicher.
  • Die Verwendung als Codierung mit fester Länge „funktioniert meistens“ in vielen gängigen Szenarien (insbesondere in den USA / EU / Ländern mit kyrillischen Alphabeten / Israel / arabischen Ländern / Iran und vielen anderen), was häufig zu einer unterbrochenen Unterstützung führt, wenn dies nicht der Fall ist. Dies bedeutet, dass die Programmierer Ersatzpaare kennen und in Fällen, in denen es darauf ankommt, richtig damit umgehen müssen!
  • Die Länge ist variabel, daher ist das Zählen oder Indizieren von Codepunkten kostspielig, jedoch weniger als UTF-8.

Im Allgemeinen ist UTF-16 für die In-Memory-Darstellung besser geeignet, da BE / LE dort irrelevant ist (nur native Reihenfolge verwenden) und die Indizierung schneller ist (vergessen Sie nur nicht, Ersatzpaare richtig zu behandeln). UTF-8 hingegen eignet sich hervorragend für Textdateien und Netzwerkprotokolle, da es kein BE / LE-Problem gibt und die Nullterminierung häufig nützlich ist sowie die ASCII-Kompatibilität.

Sergei Tachenov
quelle
3
Fehlt nur der BE / LE-Teil auf UTF16 :) UTF-8 hat einen weiteren Nachteil, es kann eine längere Ausgabe als
UTF16
4
Ja, ich habe BE / LE vergessen. Es ist jedoch keine große Sache, insbesondere für die Verwendung im Speicher. UTF-8 generiert nur dann eine längere Ausgabe, wenn es sich um Drei-Byte-Zeichen handelt. Dies bedeutet jedoch hauptsächlich Chinesisch und Japanisch. Wenn der Text hingegen viele US-ASCII-Zeichen enthält, kann dies zu einer kürzeren Ausgabe führen. Ob es sich also um einen Nachteil handelt oder nicht, hängt von einer bestimmten Situation ab.
Sergei Tachenov
Ich dachte nicht einmal daran, den unmittelbaren Profi von utf-8 zu erwähnen, der kürzer ist. In Bezug auf die längere Ausgabe von utf-8 war es aus einem bestimmten Grund "kann", aber wenn das Ziel weit im Osten liegt, sollte die Standardcodierung utf-16 sein. Wie für das Beispiel md.update (text.getBytes ("UTF-8")); Die Codierung spielt keine Rolle, da der Hash in beide Richtungen stabil ist.
Bests
Der schnellste Weg, um String in Byte-Array zu konvertieren, ist so etwas, als Beispiel veröffentlicht
bestsss
Sie sagen, dass Zeichen in UTF-8 eine unterschiedliche Länge haben, wodurch die Indizierung und Berechnung der Länge verlangsamt wird, aber ich bezweifle, dass Zeichen in UTF-16 auch eine andere Länge haben. Sollte die Indizierung und Berechnung der Länge von UTF-16 schneller sein?
nicky_zs
19

Es sind einfach verschiedene Schemata zur Darstellung von Unicode-Zeichen.

Beide sind variabel lang - UTF-16 verwendet 2 Bytes für alle Zeichen in der mehrsprachigen Basisebene (BMP), die die meisten häufig verwendeten Zeichen enthält.

UTF-8 verwendet zwischen 1 und 3 Byte für Zeichen im BMP, bis zu 4 für Zeichen im aktuellen Unicode-Bereich von U + 0000 bis U + 1FFFFF und ist auf U + 7FFFFFFF erweiterbar, falls dies jemals erforderlich wird ... Insbesondere werden jedoch alle ASCII-Zeichen jeweils in einem Byte dargestellt.

Für die Zwecke eines Nachrichtenauszugs spielt es keine Rolle, welche davon Sie auswählen, solange jeder, der versucht, den Auszug neu zu erstellen, dieselbe Option verwendet.

Auf dieser Seite finden Sie weitere Informationen zu UTF-8 und Unicode.

(Beachten Sie, dass alle Java-Zeichen UTF-16-Codepunkte innerhalb des BMP sind. Um Zeichen über U + FFFF darzustellen, müssen Sie in Java Ersatzpaare verwenden.)

Jon Skeet
quelle
5

Sicherheit: Verwenden Sie nur UTF-8

Unterschied zwischen UTF-8 und UTF-16? Warum brauchen wir diese?

Bei der Implementierung von UTF-16 gab es mindestens einige Sicherheitslücken . Siehe Wikipedia für Details .

WHATWG und W3C haben jetzt erklärt, dass nur UTF-8 im Web verwendet werden soll.

Die hier beschriebenen [Sicherheits-] Probleme verschwinden, wenn ausschließlich UTF-8 verwendet wird. Dies ist einer der vielen Gründe, die jetzt die obligatorische Codierung für alle Dinge sind.

Andere Gruppen sagen dasselbe.

Während UTF-16 möglicherweise weiterhin intern von einigen Systemen wie Java und Windows verwendet wird, wird die geringe Verwendung von UTF-16, die Sie in der Vergangenheit möglicherweise für Datendateien, Datenaustausch usw. gesehen haben, wahrscheinlich vollständig verschwinden.

Basil Bourque
quelle
4

Dies hat nichts mit UTF-8/16 zu tun (obwohl es in UTF16 konvertiert wird und der BE / LE-Teil mit einer einzelnen Zeile festgelegt werden kann), ist unten der schnellste Weg, um String in Byte [] zu konvertieren. Zum Beispiel: gut genau für den angegebenen Fall (Hash-Code). String.getBytes (enc) ist relativ langsam.

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }
bestsss
quelle
-2

Eine einfache Möglichkeit, UTF-8 und UTF-16 zu unterscheiden, besteht darin, Gemeinsamkeiten zwischen ihnen zu identifizieren.

Abgesehen davon, dass für ein bestimmtes Zeichen dieselbe Unicode-Nummer verwendet wird, hat jedes sein eigenes Format.

Venkateswara Rao
quelle