Was ist die maximale Anzahl von Bytes für ein UTF-8-codiertes Zeichen?

79

Was ist die maximale Anzahl von Bytes für ein einzelnes UTF-8-codiertes Zeichen?

Ich werde die Bytes eines in UTF-8 codierten Strings verschlüsseln und muss daher in der Lage sein, die maximale Anzahl von Bytes für einen UTF-8-codierten String zu ermitteln.

Könnte jemand bitte die maximale Anzahl von Bytes für ein einzelnes UTF-8-codiertes Zeichen bestätigen

Edd
quelle
1
Sie haben sich zuerst gemeinsame Ressourcen wie den UTF-8-Artikel von Wikipedia angesehen ... richtig?
5
Ich habe mehrere Artikel gelesen, die gemischte Antworten gaben ... Ich hatte tatsächlich den Eindruck, dass die Antwort 3 war, also bin ich sehr froh, dass ich gefragt habe
Edd
2
Ich werde hier einen Youtube-Link hinterlassen, der Tom Scotts Charaktere, Symbole und Unicode-Wunder enthält: goo.gl/sUr1Hf . Sie können hören und sehen, wie sich alles von der ASCII-Zeichencodierung zu utf-8 entwickelt.
Roy Lee
Siehe auch Berechnen der Länge in UTF-8 von Java String, ohne sie tatsächlich zu codieren, für ein Beispiel zur Berechnung des
Längencodes

Antworten:

86

Die maximale Anzahl von Bytes pro Zeichen beträgt 4 gemäß RFC3629, wodurch die Zeichentabelle auf Folgendes beschränkt wurde U+10FFFF:

In UTF-8 werden Zeichen aus dem Bereich U + 0000..U + 10FFFF (dem zugänglichen Bereich UTF-16) mit Sequenzen von 1 bis 4 Oktetten codiert.

(Die ursprüngliche Spezifikation erlaubte bis zu sechs Byte-Zeichencodes für vergangene Codepunkte U+10FFFF.)

Zeichen mit einem Code unter 128 benötigen nur 1 Byte, und die nächsten 1920 Zeichencodes benötigen nur 2 Byte. Wenn Sie nicht mit einer esoterischen Sprache arbeiten, ist das Multiplizieren der Zeichenanzahl mit 4 eine erhebliche Überschätzung.

Tamás
quelle
7
Was ist für Sie "esotherische Sprache"? Gibt es eine Sprache, die in der realen Welt existieren würde, oder einen Text, der zwischen verschiedenen Sprachen der Welt wechselt? Sollte ein Entwickler einer UTF-8-zu-String-Funktion 2, 3 oder 4 als Multiplikator wählen, wenn er eine Überzuweisung vornimmt und das Ergebnis nach der tatsächlichen Konvertierung verkleinert?
Daniel Marschall
1
@rinntech mit 'esoterischer Sprache' meint er eine Sprache mit vielen hochwertigen Unicode-Zeichen (etwas am Ende dieser Liste: unicode-table.com/en/sections ). Wenn Sie zu viel zuweisen müssen, wählen Sie 4. Sie können einen doppelten Durchgang durchführen, einen, um zu sehen, wie viele Bytes Sie benötigen und zuweisen, und einen anderen, um die Codierung durchzuführen. Das ist vielleicht besser, als das ~ 4-fache des benötigten RAM zuzuweisen.
Matiu
9
Versuchen Sie immer, den schlimmsten Fall zu behandeln: hacker9.com/single-message-can-crash-whatsapp.html
Evgen Bodunov
20
CJKV-Zeichen benötigen meistens 3 Bytes (wobei einige seltene / archaische Zeichen 4 Bytes benötigen) und sie als esoterisch zu bezeichnen, ist etwas schwierig (China allein macht fast 20% der Weltbevölkerung aus ...).
Tgr
3
Warum war es auf 4 begrenzt, als es vorher 6 war? Was hindert uns daran, den Standard fortzusetzen und ein Lead-Byte von 11111111und ein 2^(6*7)bisschen Platz für Zeichen zu haben?
Aaron Franke
32

Ohne weiteren Kontext würde ich sagen, dass die maximale Anzahl von Bytes für ein Zeichen in UTF-8 ist

Antwort: 6 Bytes

Der Autor der akzeptierten Antwort hat dies korrekt als "ursprüngliche Spezifikation" bezeichnet. Das war gültig durch RFC-2279 1 . Wie J. Cocoe in den Kommentaren unten hervorhob, änderte sich dies 2003 mit RFC-3629 2 , das UTF-8 auf die Codierung für 21 Bit beschränkt, die mit dem Codierungsschema unter Verwendung von vier Bytes verarbeitet werden kann.

Antwort, wenn alle Unicode abgedeckt: 4 Bytes

In Java <= v7 wird jedoch von einem Maximum von 3 Byte für die Darstellung von Unicode mit UTF-8 gesprochen. Dies liegt daran, dass die ursprüngliche Unicode-Spezifikation nur die grundlegende mehrsprachige Ebene ( BMP ) definiert hat, dh es handelt sich um eine ältere Version von Unicode oder eine Teilmenge des modernen Unicodes. Damit

Antwort, wenn nur der ursprüngliche Unicode dargestellt wird, das BMP: 3 Bytes

Das OP spricht jedoch davon, in die andere Richtung zu gehen. Nicht von Zeichen zu UTF-8-Bytes, sondern von UTF-8-Bytes zu einer "Zeichenfolge" der Bytedarstellung. Vielleicht hat der Autor der akzeptierten Antwort dies aus dem Kontext der Frage erhalten, aber dies ist nicht unbedingt offensichtlich, was den gelegentlichen Leser dieser Frage verwirren kann.

Beim Übergang von UTF-8 zur nativen Codierung müssen wir uns ansehen, wie der "String" implementiert ist. Einige Sprachen, wie Python> = 3, repräsentieren jedes Zeichen mit ganzzahligen Codepunkten, was 4 Bytes pro Zeichen = 32 Bit ermöglicht, um die 21, die wir für Unicode benötigen, mit etwas Verschwendung abzudecken. Warum nicht genau 21 Bit? Weil die Dinge schneller sind, wenn sie byteorientiert sind. Einige Sprachen wie Python <= 2 und Java stellen Zeichen mit einer UTF-16-Codierung dar. Dies bedeutet, dass sie Ersatzpaare verwenden müssen, um erweiterten Unicode (nicht BMP) darzustellen. In beiden Fällen sind das immer noch maximal 4 Bytes.

Antwort, wenn UTF-8 -> native Codierung verwendet wird: 4 Bytes

Letztendlich ist 4 die häufigste richtige Antwort, also haben wir es richtig verstanden. Der Kilometerstand kann jedoch variieren.

Joshua Richardson
quelle
5
"Dies ist immer noch die aktuelle und korrekte Spezifikation per Wikipedia" - nicht mehr. Kurz nachdem Sie dies geschrieben haben (2. April), wurde der UTF-8-Artikel von Wikipedia geändert, um zu verdeutlichen, dass die 6-Oktett-Version nicht Teil der aktuellen UTF-8-Spezifikation (2003) ist.
J. Cocoe
"Aber in Java <= v7 sprechen sie von einem 3-Byte-Maximum für die Darstellung von Unicode mit UTF-8? Das liegt daran, dass die ursprüngliche Unicode-Spezifikation nur die grundlegende mehrsprachige Ebene definiert hat" - Das ist wahrscheinlich der ursprüngliche Grund, aber Es ist nicht die ganze Geschichte. Java verwendet "modifiziertes UTF-8", und eine der Modifikationen besteht darin, dass es "sein eigenes Zwei-mal-Drei-Byte-Format" anstelle des "Vier-Byte-Formats von Standard-UTF-8" (deren Wörter) verwendet.
J. Cocoe
1
Es gibt keine Codepunkte, die über dem 10FFFF-Limit (etwas mehr als eine Million) liegen, und viele der UTF8-Implementierungen haben niemals Sequenzen implementiert, die länger als 4 Bytes sind (und einige nur 3, z. B. MySQL) Codepoint auch unter Berücksichtigung der Kompatibilität mit älteren Implementierungen. Sie müssen nur sicherstellen, dass Sie auf dem Weg nach innen alles ungültige verwerfen. Beachten Sie, dass die Empfehlung von matiu, nach der Berechnung der exakten Bytelänge zuzuweisen, nach Möglichkeit gut ist.
Thomasrutter
2
"... [U] nicode kann bis zu x10FFFF-Codepunkte darstellen. Einschließlich 0 bedeutet dies, dass wir dies mit diesen Bytes tun können: F FF FF, dh zweieinhalb Bytes oder 20 Bits." Ich glaube das ist ein bisschen falsch. Die Anzahl der Codepunkte von 0x0 bis 0x10FFFF wäre 0x110000, die in 1F FF FFoder 21 Bit dargestellt werden könnten . Die 0x110000-Nummer entspricht den 17 Ebenen mit jeweils 0x10000-Codepunkten.
Neuralmer
2
PSA: Wikipedia ist keine echte Quelle. Schauen Sie sich die tatsächlichen Referenzen des Artikels an.
Nyerguds
0

Die maximale Anzahl von Bytes zur Unterstützung von US-ASCII, einer Standardcodierung des englischen Alphabets, beträgt 1. Die Beschränkung des Textes auf Englisch wird jedoch mit der Zeit weniger wünschenswert oder praktisch.

Unicode wurde entwickelt, um die Glyphen aller menschlichen Sprachen sowie viele Arten von Symbolen mit einer Vielzahl von Rendering-Eigenschaften darzustellen. UTF-8 ist eine effiziente Codierung für Unicode, obwohl sie immer noch auf Englisch ausgerichtet ist. UTF-8 ist selbstsynchronisierend: Zeichengrenzen können leicht identifiziert werden, indem in beiden Richtungen nach genau definierten Bitmustern gesucht wird.

Während die maximale Anzahl von Bytes pro UTF-8-Zeichen 3 beträgt, um nur den 2-Byte-Adressraum von Ebene 0, der mehrsprachigen Basisebene (BMP), zu unterstützen, die in einigen Anwendungen als minimale Unterstützung akzeptiert werden kann, beträgt sie 4 für die Unterstützung alle 17 aktuellen Flugzeuge von Unicode (Stand 2019). Es sollte beachtet werden, dass sich wahrscheinlich viele beliebte "Emoji" -Zeichen in Ebene 16 befinden, für die 4 Bytes erforderlich sind.

Dies gilt jedoch nur für Glyphen mit Grundzeichen. Es gibt auch verschiedene Modifikatoren, z. B. das Anzeigen von Akzenten über dem vorherigen Zeichen, und es ist auch möglich, eine beliebige Anzahl von Codepunkten miteinander zu verknüpfen, um ein komplexes "Graphem" zu erstellen. In der realen Programmierung führt die Verwendung oder Annahme einer festen maximalen Anzahl von Bytes pro Zeichen wahrscheinlich zu einem Problem für Ihre Anwendung.

Diese Überlegungen implizieren, dass UTF-8-Zeichenfolgen vor der Verarbeitung nicht wie manchmal zu Arrays fester Länge "erweitert" werden sollten. Stattdessen sollte die Programmierung direkt mit String-Funktionen erfolgen, die speziell für UTF-8 entwickelt wurden.

David Spector
quelle
Hinweis: Der Absatz über die Nichtverwendung eines Zeichenfelds mit fester Breite ist meiner Meinung nach. Ich bin bereit, diese Antwort als Antwort auf Kommentare zu bearbeiten.
David Spector