Wie viele Zeichen kann UTF-8 codieren?


97

Wenn UTF-8 8 Bit umfasst, bedeutet dies nicht, dass nur maximal 256 verschiedene Zeichen vorhanden sein können?

Die ersten 128 Codepunkte sind dieselben wie in ASCII. Aber es heißt, dass UTF-8 bis zu Millionen von Zeichen unterstützen kann?

Wie funktioniert das?


2
Wenn Sie diese Frage bitte neu bewerten könnten, da alle Antworten falsch sind. Lesen Sie meine Antwort: stackoverflow.com/a/45042566/124486
Evan Carroll

Bei den UTF-8-, UTF-16- und UTF-32-Codierungen von Unicode ist die Anzahl die Anzahl der Bits in ihren Codeeinheiten , von denen eines oder mehrere einen Unicode-Codepunkt codieren.
Tom Blodget

1
Ich habe diese Frage vor einiger Zeit beantwortet, um sie zu klären: Es wäre großartig, wenn Sie sie gegen die gewählte Antwort abwägen würden, die buchstäblich nur ein einziges Wikipedia-Zitat ist, das nicht die ganze Geschichte erzählt (hoffentlich mein Update) ist viel klarer)
Evan Carroll

Antworten:


135

UTF-8 verwendet nicht immer ein Byte, sondern 1 bis 4 Byte.

Die ersten 128 Zeichen (US-ASCII) benötigen ein Byte.

Die nächsten 1.920 Zeichen benötigen zwei Bytes zum Codieren. Dies umfasst den Rest fast aller lateinischen Alphabete sowie griechische, kyrillische, koptische, armenische, hebräische, arabische, syrische und Tāna-Alphabete sowie die Kombination diakritischer Zeichen.

Drei Bytes werden für Zeichen im Rest der mehrsprachigen Grundebene benötigt, die praktisch alle gebräuchlichen Zeichen enthält [12], einschließlich der meisten chinesischen, japanischen und koreanischen [CJK] Zeichen.

Für Zeichen in den anderen Ebenen von Unicode werden vier Bytes benötigt, darunter weniger gebräuchliche CJK-Zeichen, verschiedene historische Skripte, mathematische Symbole und Emoji (piktografische Symbole).

Quelle: Wikipedia


hi @zwippie ich neu in diesem. Es gibt etwas, das ich nicht verstehe.! BMP verwendet 2 Bytes, von denen Sie sagen, dass sie 3 sind? Liege ich falsch?
Chiperortiz

1
@chiperortiz, BMP ist in der Tat 16 Bit, daher kann es als UTF-16 mit konstanter Länge pro Zeichen codiert werden (UTF-16 unterstützt auch das Überschreiten von 16 Bit, aber es ist eine schwierige Praxis, und viele Implementierungen unterstützen es nicht). Für UTF-8 müssen Sie jedoch auch codieren, wie lange es dauern wird, damit Sie einige Bits verlieren. Aus diesem Grund benötigen Sie 3 Bytes, um das gesamte BMP zu codieren. Dies mag als verschwenderisch erscheinen, aber denken Sie daran, dass UTF-16 immer 2 Bytes verwendet, UTF-8 jedoch ein Byte pro Zeichen für die meisten lateinischen Sprachzeichen. Machen Sie es doppelt so kompakt.
Sanderd17

Der Hauptschwerpunkt der OP-Frage hängt damit zusammen, warum sie UTF- 8 heißt - das beantwortet das nicht wirklich.
13.

39

UTF-8 verwendet 1-4 Bytes pro Zeichen: ein Byte für ASCII-Zeichen (die ersten 128 Unicode-Werte sind dieselben wie bei ASCII). Das erfordert aber nur 7 Bits. Wenn das höchste Bit ("Vorzeichen") gesetzt ist, zeigt dies den Beginn einer Mehrbyte-Sequenz an. Die Anzahl der aufeinanderfolgenden hohen Bits gibt die Anzahl der Bytes an, dann eine 0, und die verbleibenden Bits tragen zum Wert bei. Für die anderen Bytes sind die höchsten zwei Bits 1 und 0 und die verbleibenden 6 Bits sind für den Wert.

Eine Vier-Byte-Sequenz würde also mit 11110 beginnen ... (und ... = drei Bits für den Wert), dann drei Bytes mit jeweils 6 Bits für den Wert, was einen 21-Bit-Wert ergibt. 2 ^ 21 überschreitet die Anzahl der Unicode-Zeichen, sodass der gesamte Unicode in UTF8 ausgedrückt werden kann.


@ NickL. Nein, ich meine 3 Bytes. In diesem Beispiel, wenn das erste Byte eines Mehrbyte - Sequenz 1111 beginnt, zeigt die erste 1 , dass es ist der Beginn einer Multibyte - Sequenz, dann ist die Anzahl von aufeinanderfolgenden 1'en Danach gibt die Anzahl der zusätzlichen Bytes in der Folge (so ein erstes Byte beginnt entweder 110, 1110 oder 11110).
CodeClown42

Beweise für Ihre Worte in RFC 3629 gefunden . Tools.ietf.org/html/rfc3629#section-3 . Ich verstehe jedoch nicht, warum ich "10" am Anfang des zweiten Bytes 110xxxxx 10xxxxxx platzieren muss. Warum nicht einfach 110xxxxx xxxxxxxx?
Kolobok

3
Antwort in softwareengineering.stackexchange.com/questions/262227/… gefunden . Nur aus Sicherheitsgründen (falls ein einzelnes Byte in der Mitte des Streams beschädigt ist)
Kolobok

@ Kolobok Ah. Ohne Sicherheit können Sie dann einen 21-Bit-Wert in 3 Bytes codieren (3 Bit geben die Länge an, plus 21 Bit). : D Wahrscheinlich ist das aber nicht so aussagekräftig, zumindest die westlichen WRT-Sprachen.
CodeClown42

Ich vermute, dass NickL dies gefragt hat, aber was ist mit den restlichen Bits in diesem ersten Byte passiert, wenn ... nachfolgende Bytes anstelle von Bits darstellt?
c6754

26

Gemäß dieser Tabelle sollte * UTF-8 Folgendes unterstützen:

2 31 = 2.147.483.648 Zeichen

RFC 3629 hat jedoch die möglichen Werte eingeschränkt, sodass wir jetzt auf 4 Byte begrenzt sind , was uns gibt

2 21 = 2.097.152 Zeichen

Beachten Sie, dass ein guter Teil dieser Zeichen für die benutzerdefinierte Verwendung "reserviert" ist, was für Symbolschriftarten eigentlich sehr praktisch ist.

* Wikipedia verwendet zeigt eine Tabelle mit 6 Bytes - sie haben den Artikel seitdem aktualisiert.

2017-07-11: Korrigiert für die Doppelzählung desselben Codepunkts, der mit mehreren Bytes codiert ist


Diese Antwort zählt die Anzahl der möglichen Codierungen doppelt. Sobald Sie alle 2 ^ 7 gezählt haben, können Sie sie in 2 ^ 11, 2 ^ 16 usw. nicht mehr zählen. Die richtige Anzahl möglicher Codierungen ist 2 ^ 21 (obwohl derzeit nicht alle verwendet werden).
Jimmy

@ Jimmy Bist du sicher, dass ich doppelt zähle? 0xxxxxxxgibt 7 verwendbare Bits, 110xxxxx 10xxxxxxgibt 11 mehr - es gibt keine Überlappung. Das erste Byte beginnt 0im ersten Fall und 1im zweiten Fall mit.
Mpen

@mpen also welcher Codepunkt 00000001speichert und was 11000000 100000001speichert?
Evan Carroll

1
@EvanCarroll Uhh .... Punkt genommen. Ich wusste nicht, dass es mehrere Möglichkeiten gibt, denselben Codepunkt zu codieren.
Mpen

1
Ich habe versucht, dies selbst zu beantworten, um zu sehen, ob dies eine bessere Erklärung und Antwort auf die Frage ist: stackoverflow.com/a/45042566/124486
Evan Carroll

21

Unicode gegen UTF-8

Unicode löst Codepunkte in Zeichen auf. UTF-8 ist ein Speichermechanismus für Unicode. Unicode hat eine Spezifikation. UTF-8 hat eine Spezifikation. Sie haben beide unterschiedliche Grenzen. UTF-8 hat eine andere Aufwärtsbindung.

Unicode

Unicode wird mit "Ebenen" bezeichnet. Jedes Flugzeug trägt 2 16 Codepunkte. Es gibt 17 Flugzeuge in Unicode. Für insgesamt 17 * 2^16Codepunkte. Die erste Ebene, Ebene 0 oder BMP , hat ein besonderes Gewicht.

Anstatt alle Nuancen zu erklären, möchte ich nur den obigen Artikel über Flugzeuge zitieren.

Die 17 Flugzeuge können 1.114.112 Codepunkte aufnehmen. Davon sind 2.048 Ersatzzeichen, 66 Nichtzeichen und 137.468 sind für den privaten Gebrauch reserviert, so dass 974.530 für öffentliche Aufgaben übrig bleiben.

UTF-8

Kehren wir nun zu dem oben verlinkten Artikel zurück.

Das von UTF-8 verwendete Codierungsschema wurde mit einer viel größeren Grenze von 2 31 Codepunkten (32.768 Ebenen) entworfen und kann 2 21 Codepunkte (32 Ebenen) codieren, selbst wenn es auf 4 Bytes begrenzt ist. [3] Da Unicode die Codepunkte auf die 17 Ebenen beschränkt, die von UTF-16 codiert werden können, sind Codepunkte über 0x10FFFF in UTF-8 und UTF-32 ungültig.

So können Sie sehen, dass Sie Dinge in UTF-8 einfügen können, die kein gültiger Unicode sind. Warum? Weil UTF-8 Codepunkte enthält, die Unicode nicht einmal unterstützt.

UTF-8 unterstützt trotz einer Beschränkung auf vier Byte 2 21 Codepunkte, was weit mehr als ist17 * 2^16


18

2.164.864 "Zeichen" können möglicherweise von UTF-8 codiert werden.

Diese Zahl ist 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21, was sich aus der Funktionsweise der Codierung ergibt:

  • 1-Byte-Zeichen haben 7 Bits für die Codierung 0xxxxxxx(0x00-0x7F)

  • 2-Byte-Zeichen haben 11 Bit zum Codieren 110xxxxx 10xxxxxx(0xC0-0xDF für das erste Byte; 0x80-0xBF für das zweite)

  • 3-Byte-Zeichen haben 16 Bit zum Codieren 1110xxxx 10xxxxxx 10xxxxxx(0xE0-0xEF für das erste Byte; 0x80-0xBF für Fortsetzungsbytes)

  • 4-Byte-Zeichen haben 21 Bits für die Codierung 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(0xF0-0xF7 für das erste Byte; 0x80-0xBF für Fortsetzungsbytes)

Wie Sie sehen, ist dies deutlich größer als der aktuelle Unicode (1.112.064 Zeichen).

AKTUALISIEREN

Meine anfängliche Berechnung ist falsch, da zusätzliche Regeln nicht berücksichtigt werden. Weitere Informationen finden Sie in den Kommentaren zu dieser Antwort.


2
Ihre Mathematik respektiert nicht die UTF-8-Regel, dass nur die kürzeste Codeeinheitssequenz einen Codepunkt codieren darf. 00000001 ist also gültig für U + 0001, 11110000 10000000 10000000 10000001 jedoch nicht. Ref: Tabelle 3-7. Gut geformte UTF-8-Byte-Sequenzen . Außerdem wird die Frage direkt von der Tabelle beantwortet: Sie addieren einfach die Bereiche. (Sie sind disjunkt, um Ersatz für UTF-16 auszuschließen).
Tom Blodget

Tom - danke für deinen Kommentar! Diese Einschränkungen waren mir nicht bekannt. Ich habe Tabelle 3-7 gesehen und die Zahlen eingegeben und es sieht so aus, als ob es 1.083.392 mögliche gültige Sequenzen gibt.
Ruben Reyes

6

UTF-8 ist eine Codierung mit variabler Länge mit mindestens 8 Bit pro Zeichen.
Zeichen mit höheren Codepunkten benötigen bis zu 32 Bit.


2
Das ist irreführend. Der längste Codepunkt, den Sie haben können, ist 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, sodass nur 21 Bit zum Codieren des tatsächlichen Zeichens verwendet werden können.
Boris

5
Ich sagte, dass die Codierung von Codepunkten bis zu 32 Bit dauern kann. Ich habe nie behauptet, dass Sie (durch Induktion) 2 ^ 32 Zeichen in 32-Bit-UTF-8 codieren können. Aber das ist eher fraglich, da Sie kodieren , können alle vorhandenen Unicode - Zeichen in UTF-8, und Sie können sogar mehr kodieren , wenn Sie UTF-8 bis 48 Bits strecken (was existiert , ist aber veraltet), so dass ich nicht sicher bin , was die irreführender Punkt ist.
Täuschung


2

Lesen Sie den Unicode-Standard und zugehörige Informationen, z. B. den FAQ-Eintrag. UTF-8 UTF-16, UTF-32 und Stückliste . Es ist nicht so reibungslos, aber es sind maßgebliche Informationen, und vieles, was Sie an anderer Stelle über UTF-8 lesen könnten, ist fraglich.

Die "8" in "UTF-8" bezieht sich auf die Länge von Codeeinheiten in Bits. Codeeinheiten sind Entitäten, die zum Codieren von Zeichen verwendet werden, nicht unbedingt als einfache Eins-zu-Eins-Zuordnung. UTF-8 verwendet eine variable Anzahl von Codeeinheiten, um ein Zeichen zu codieren.

Die Sammlung von Zeichen, die in UTF-8 codiert werden können, ist genau die gleiche wie für UTF-16 oder UTF-32, dh alle Unicode-Zeichen. Sie alle codieren den gesamten Unicode-Codierungsbereich, der sogar Nichtzeichen und nicht zugewiesene Codepunkte enthält.


1

Obwohl ich mit mpen in Bezug auf die aktuellen maximalen UTF-8-Codes (2.164.864) einverstanden bin (siehe unten, ich konnte seine nicht kommentieren), ist er um 2 Stufen versetzt, wenn Sie die 2 Hauptbeschränkungen von UTF-8 entfernen: nur 4 Bytes Limit und Codes 254 und 255 können nicht verwendet werden (er hat nur das 4-Byte-Limit entfernt).

Der Startcode 254 folgt der Grundanordnung der Startbits (Mehrbit-Flag auf 1 gesetzt, eine Anzahl von 6 1 und Terminal 0, keine Ersatzbits), wodurch Sie 6 zusätzliche Bytes zum Arbeiten erhalten (6 10xxxxxx-Gruppen, zusätzliche 2 ^ 36 Codes).

Der Startcode 255 folgt nicht genau der Grundeinstellung, es wird kein Terminal 0 verwendet, aber alle Bits werden verwendet, wodurch Sie 7 zusätzliche Bytes erhalten (Multi-Bit-Flag auf 1 gesetzt, eine Anzahl von 7 1 und kein Terminal 0, da alle Bits verwendet werden ; 7 10xxxxxx Gruppen, zusätzlich 2 ^ 42 Codes).

Wenn Sie diese hinzufügen, erhalten Sie einen endgültigen maximal darstellbaren Zeichensatz von 4.468.982.745.216. Dies sind mehr als alle derzeit verwendeten Zeichen, alte oder tote Sprachen und alle vermutlich verlorenen Sprachen. Engels- oder Himmelsschrift jemand?

Neben 254 und 255: 128-191 und einigen anderen gibt es auch Einzelbyte-Codes, die im UTF-8-Standard übersehen / ignoriert werden. Einige werden lokal von der Tastatur verwendet, Beispielcode 128 ist normalerweise ein Rückraum zum Löschen. Die anderen Startcodes (und zugehörigen Bereiche) sind aus einem oder mehreren Gründen ungültig ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).


0

Unicode ist fest mit UTF-8 verheiratet. Unicode unterstützt speziell 2 ^ 21 Codepunkte (2.097.152 Zeichen), was genau der Anzahl der von UTF-8 unterstützten Codepunkte entspricht. Beide Systeme reservieren den gleichen "Totraum" und die gleichen Sperrzonen für Codepunkte usw. ... Ab Juni 2018 enthält die neueste Version, Unicode 11.0, ein Repertoire von 137.439 Zeichen

Aus dem Unicode-Standard. Unicode-FAQ

Der Unicode-Standard codiert Zeichen im Bereich U + 0000..U + 10FFFF, was einem 21-Bit-Codebereich entspricht.

Von der UTF-8 Wikipedia-Seite. UTF-8 Beschreibung

Seit der Beschränkung des Unicode-Code-Space auf 21-Bit-Werte im Jahr 2003 ist UTF-8 so definiert, dass Codepunkte in ein bis vier Bytes, ...


21 Bits werden aufgerundet. Unicode unterstützt 1.114.112 Codepunkte (U + 0000 bis U + 10FFFF), wie es heißt. (Manchmal als 17 Flugzeuge von 65536 beschrieben.)
Tom Blodget

@ TomBlodget, Sie sind richtig. Die wichtigste Erkenntnis aus dieser Diskussion ist, dass UTF-8 alle derzeit im Unicode-Standard definierten Punkte codieren kann und dies wahrscheinlich noch einige Zeit tun wird.
Anzeigename
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.