Wie viele Bytes benötigt ein Unicode-Zeichen?

238

Ich bin ein bisschen verwirrt über Codierungen. Soweit ich weiß, haben alte ASCII-Zeichen ein Byte pro Zeichen benötigt. Wie viele Bytes benötigt ein Unicode-Zeichen?

Ich gehe davon aus, dass ein Unicode-Zeichen jedes mögliche Zeichen aus einer beliebigen Sprache enthalten kann - bin ich richtig? Wie viele Bytes benötigt es pro Zeichen?

Und was bedeuten UTF-7, UTF-6, UTF-16 usw.? Sind sie verschiedene Versionen von Unicode?

Ich habe den Wikipedia-Artikel über Unicode gelesen, aber es ist ziemlich schwierig für mich. Ich freue mich auf eine einfache Antwort.

nan
quelle
15
Entschuldigung, es gibt keine einfache Antwort. Ich finde das Ganze ein bisschen chaotisch. Unicode wurde mit zwei Bytes in Rechnung gestellt und konnte alle Zeichen darstellen, aber es stellte sich heraus, dass zwei Bytes nicht genug waren.
Jonathan Wood
12
"Einfache Antwort": Ein Unicode-Zeichen benötigt 1-4 Bytes. Unicode deckt viele Sprachen ab, aber nicht alle. Als ich das letzte Mal nachgesehen habe, war Klingonisch beispielsweise kein offizieller Unicode-Zeichensatz.
Peter G.
9
Klingonisch ist nicht Teil des Unicode-Standards selbst, nein. Stattdessen wird der private Nutzungsbereich von Uniode (U + F8D0 - U + F8FF) verwendet.
Remy Lebeau
1
Retterfrage - danke. Meine Situation ist das Speichern von Daten über SCORM 1.2-kompatible LMS ... Der Standard für SCORM 1.2 'cmi.suspend_data' sind 4096 Datenbytes, von denen ein früherer Entwickler angenommen hat, dass wir 4096 Zeichen speichern können. Oh Mann, hat er sich geirrt? Ich habe gerade herausgefunden, warum unser Lesezeichen bei langen Kursen fehlschlägt. Jetzt weiß ich also, da wir UTF-8 verwenden, werden 4 Bytes pro Zeichen benötigt, was 1024 Zeichen ergibt.
Danjah

Antworten:

146

Sie werden keine einfache Antwort sehen, weil es keine gibt.

Erstens enthält Unicode nicht "jedes Zeichen aus jeder Sprache", obwohl es dies sicher versucht.

Unicode selbst ist eine Zuordnung, es definiert Codepunkte und ein Codepunkt ist eine Zahl, die normalerweise einem Zeichen zugeordnet ist. Ich sage normalerweise, weil es Konzepte wie das Kombinieren von Zeichen gibt. Sie kennen möglicherweise Dinge wie Akzente oder Umlaute. Diese können mit einem anderen Zeichen verwendet werden, z. B. einem aoder einem u, um ein neues logisches Zeichen zu erstellen. Ein Zeichen kann daher aus einem oder mehreren Codepunkten bestehen.

Um in Computersystemen nützlich zu sein, müssen wir eine Darstellung für diese Informationen auswählen. Dies sind die verschiedenen Unicode-Codierungen wie utf-8, utf-16le, utf-32 usw. Sie unterscheiden sich weitgehend durch die Größe ihrer Codeeinheiten. UTF-32 ist die einfachste Codierung. Es hat eine Codeeinheit mit 32 Bit, was bedeutet, dass ein einzelner Codepunkt bequem in eine Codeeinheit passt. Bei den anderen Codierungen treten Situationen auf, in denen ein Codepunkt mehrere Codeeinheiten benötigt oder dieser bestimmte Codepunkt in der Codierung überhaupt nicht dargestellt werden kann (dies ist beispielsweise bei UCS-2 ein Problem).

Aufgrund der Flexibilität beim Kombinieren von Zeichen kann die Anzahl der Bytes pro Zeichen selbst innerhalb einer bestimmten Codierung je nach Zeichen und Normalisierungsform variieren. Dies ist ein Protokoll für den Umgang mit Zeichen, die mehr als eine Darstellung haben (Sie können sagen, "an 'a' with an accent"dass es sich um 2 Codepunkte handelt, von denen einer ein Kombinationszeichen oder "accented 'a'"ein Codepunkt ist).

Logan Capaldo
quelle
1
OK. Wie viele Bytes benötigt dann ein bestimmtes Zeichen, das in einem bestimmten Codepunkt dargestellt wird? Zum Beispiel der nicht unterbrechende Raum.
Nicolas Barbulesco
Die kombinierten Zeichen machen das Leben eines Programmierers zur Hölle, wenn es darum geht, strlen (), substr () und andere Funktionen zur Manipulation von Zeichenfolgen auf UTF8-Arrays zu schreiben. Diese Art von Arbeit wird niemals abgeschlossen und immer fehlerhaft sein.
Nulik
Ich habe eine Demo geschrieben, die Windows-1252-, UTF8- und UTF8-BOM-codierte Dateien zeigt, die mit jeder Codierung interpretiert werden, und die Gleichheit zwischen den Ergebnissen vergleicht: github.com/vladyrn/encodings_demo
Vlad
195

Seltsamerweise hat niemand darauf hingewiesen, wie zu berechnen ist, wie viele Bytes ein Unicode-Zeichen benötigt. Hier ist die Regel für UTF-8-codierte Zeichenfolgen:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Die schnelle Antwort lautet also: Es dauert 1 bis 4 Bytes, abhängig vom ersten, das angibt, wie viele Bytes es aufnehmen wird.

paul.ago
quelle
8
Ich glaube, der maximale Hex-Wert für ein 4-Byte-Zeichen ist 0xF7 (nicht 0xF4).
DJPJ
Ich danke dir sehr! Ich habe nur den IETF-Standard durchgesteuert und nichts über das Codieren gefunden, und der Artikel, den ich las, ging nicht detailliert genug, um zu sagen, wie viele Bits verwendet werden, um die Anzahl des nachfolgenden Codes darzustellen Punkte pro "Zeichen".
MarcusJ
1
Dies ist jetzt auf der zweiten Seite meines Spickzettel "Einführung für neue Teammitglieder", zusammen mit den lustigen ersten beiden Kommentaren
Cee McSharpface
1
0xF4 war kein Fehler, sondern eine Klarstellung. Unicode-Codepunkte liegen im Bereich von 0 bis 0 x 10ffff, sodass der letzte Codepunkt als F4 8F BF BF codiert ist.
Frediano Ziglio
38

Ich weiß, dass diese Frage alt ist und bereits eine akzeptierte Antwort hat, aber ich möchte einige Beispiele anbieten (in der Hoffnung, dass sie für jemanden nützlich sein wird).

Soweit ich weiß, haben alte ASCII-Zeichen ein Byte pro Zeichen benötigt.

Richtig. Da es sich bei ASCII um eine 7-Bit-Codierung handelt, werden 128 Codes unterstützt (von denen 95 druckbar sind), sodass nur ein halbes Byte verwendet wird (sofern dies sinnvoll ist).

Wie viele Bytes benötigt ein Unicode-Zeichen?

Unicode ordnet nur Zeichen Codepunkten zu. Es definiert nicht, wie sie codiert werden sollen. Eine Textdatei enthält keine Unicode-Zeichen, sondern Bytes / Oktette, die Unicode-Zeichen darstellen können.

Ich gehe davon aus, dass ein Unicode-Zeichen jedes mögliche Zeichen aus einer beliebigen Sprache enthalten kann - bin ich richtig?

Nein, aber fast. Also im Grunde ja. Aber immer noch nein.

Wie viele Bytes benötigt es pro Zeichen?

Gleich wie deine 2. Frage.

Und was bedeuten UTF-7, UTF-6, UTF-16 usw.? Sind sie eine Art Unicode-Versionen?

Nein, das sind Kodierungen. Sie definieren, wie Bytes / Oktette Unicode-Zeichen darstellen sollen.

Ein paar Beispiele. Wenn einige davon nicht in Ihrem Browser angezeigt werden können (wahrscheinlich, weil die Schriftart sie nicht unterstützt), gehen Sie zu http://codepoints.net/U+1F6AA(durch 1F6AAden Codepunkt in Hex ersetzen ), um ein Bild anzuzeigen .

    • U + 0061 LATEINISCHER KLEINBUCHSTABE A: a
      • Nr.: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • U + 00A9 COPYRIGHT-ZEICHEN: ©
      • Nr.: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • U + 00AE REGISTRIERTES ZEICHEN: ®
      • Nr.: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 ÄTHIOPISCH SYLLABLE PHWA:
      • Nr.: 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • Nr.: 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • U + 2030 PRO MILLE-ZEICHEN:
      • Nr.: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20-30
    • U + 20AC EURO ZEICHEN:
      • Nr.: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • U + 2122 MARKENZEICHEN:
      • Nr.: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 SNOWMAN:
      • Nr.: 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • U + 260E SCHWARZES TELEFON:
      • Nr.: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • U + 2614 REGENSCHIRM MIT REGENTROPFEN:
      • Nr.: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A WEISSES LÄCHELN:
      • Nr.: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 SCHWARZE FLAGGE:
      • Nr.: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • U + 269B ATOM SYMBOL:
      • Nr.: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • U + 2708 FLUGZEUG:
      • Nr.: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E SHADOWED WHITE LATIN CROSS:
      • Nr.: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 POSTMARKENGESICHT:
      • Nr.: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK UNIFIED IDEOGRAPH-8089:
      • Nr.: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 POO-STAPEL: 💩
      • Nr.: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • U + 1F680 RAKETE: 🚀
      • Nr.: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Okay, ich werde mitgerissen ...

Wissenswertes:

basic6
quelle
Die Codeeinheiten in UTF-16 sind 16 Bit breit. Sie haben sie mit einem Leerzeichen in der Mitte gezeigt, was irreführend ist. Die UTF-16-Darstellung für © sollte eher 00A9anstelle von 00 A9(was UTF-16BE wäre) sein.
Roland Illig
Was ist der Unterschied? Steht BE nicht für Big Endian? Er hat es in Big Endian geschrieben, und so wäre eine in Big Endian UTF-16 geschriebene Datei dieselbe wie UTF-16BE, oder?
HappyPandaFace
6
Korrekturen: 1) ASCII ist 7 Bit, ein Byte ist 8 Bit, also viel mehr als die Hälfte. 2) Unicode definiert, wie die Codepunkte codiert werden. UTF-8, UTF-16 und UTF-32 sind im Unicode-Standard definiert.
Jonathan Rosenne
3
@ JonathanRosenne Ich denke, er / sie meinte, dass es nur die Hälfte der möglichen Werte verwendet, die mit 8 Bits darstellbar sind, nicht, dass es die Hälfte der Bits verwendet.
Aritz Lopez
2
Ich mag die Beispiele wirklich. Sie zeigen auf, warum man beispielsweise UTF-16 UTF-8 vorziehen kann. Entwickler unterschiedlicher Software können unterschiedliche Codierungen auswählen, basierend darauf, welche Unicode-Zeichen mit größerer Wahrscheinlichkeit verwendet werden. In China / Japan zum Beispiel ist UTF-16 (2 Byte) für sie sinnvoller als UTF-8, da dieselben Zeichen häufig doppelt so viele Bytes benötigen, um in UTF-8 zu codieren
Mike
29

Einfach gesagt Unicodeist ein Standard, der allen Zeichen der Welt eine Nummer (Codepunkt genannt) zuweist (es ist noch in Arbeit).

Jetzt müssen Sie diese Codepunkte mit Bytes darstellen, die aufgerufen werden character encoding. UTF-8, UTF-16, UTF-6sind Möglichkeiten, diese Zeichen darzustellen.

UTF-8ist eine Multibyte-Zeichencodierung. Zeichen können 1 bis 6 Bytes haben (einige von ihnen sind derzeit möglicherweise nicht erforderlich).

UTF-32 Jedes Zeichen hat 4 Bytes pro Zeichen.

UTF-16verwendet 16 Bit für jedes Zeichen und stellt nur einen Teil der Unicode-Zeichen dar, die als BMP bezeichnet werden (für alle praktischen Zwecke ist dies ausreichend). Java verwendet diese Codierung in seinen Zeichenfolgen.

Simbabao
quelle
10
Unicode ist ein 21-Bit-Codesatz und 4 Bytes reichen aus, um ein Unicode-Zeichen in UTF-8 darzustellen. UTF-16 verwendet Ersatzzeichen, um Zeichen außerhalb des BMP (grundlegende mehrsprachige Ebene) darzustellen. Es benötigt entweder 2 oder 4 Bytes, um ein gültiges Unicode-Zeichen darzustellen. UCS-2 war die einzige 16-Bit-Variante von UTF-16 ohne Unterstützung für Ersatzzeichen oder Zeichen außerhalb des BMP.
Jonathan Leffler
1
Du hast Recht. UTF-8 Original hatte 6 Bytes, um ein 32-Bit aufzunehmen. Ich wollte die Dinge eigentlich nicht viel komplizieren, da er bereits mit dem Wiki-Dokument verwechselt wurde :)
Zimbabao
3
Diese Antwort besagt, dass UTF-16 keine BMP-Codepunkte codieren kann. Dies ist falsch, da diese genauso wie in UTF-8 mit Ersatzpaaren codiert werden können. (Sie müssen an das veraltete UCS-2 denken, bevor Unicode 2.0 herauskam, das nur 16-Bit-Codepunkte codierte.) Außerdem verwendet Java UTF-16 nicht ganz, sondern eine modifizierte Form davon, in der der Code zeigt 0 ist anders codiert.
Rdb
@rdb - Es ist das Gegenteil. Die Antwort besagt, dass UTF-16 das BMP darstellt.
Nicolas Barbulesco
3
Ich habe falsch getippt; Ich wollte "Nicht-BMP" sagen. Der Fehler in der Antwort besteht darin, dass UTF-16 BMP-Zeichen darstellt, was ungenau ist. UTF-16 kann alle Unicode-Zeichen codieren - Nicht-BMP-Zeichen werden über Ersatzpaare codiert. Vielleicht war der Antwortende mit UCS-2 verwechselt.
Rdb
17

In UTF-8:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

In UTF-16:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

In UTF-32:

4 bytes:      0 - 10FFFF

10FFFF ist per Definition der letzte Unicode-Codepunkt und wird auf diese Weise definiert, da es sich um das technische Limit von UTF-16 handelt.

Es ist auch der größte Codepunkt, den UTF-8 in 4 Byte codieren kann, aber die Idee hinter der Codierung von UTF-8 funktioniert auch für 5- und 6-Byte-Codierungen, um Codepunkte bis 7FFFFFFF abzudecken, d. H. die Hälfte von dem, was UTF-32 kann.

John
quelle
8

In Unicode ist die Antwort nicht einfach zu geben. Das Problem sind, wie Sie bereits betont haben, die Codierungen.

Bei jedem englischen Satz ohne diakritische Zeichen wäre die Antwort für UTF-8 so viele Bytes wie Zeichen und für UTF-16 wäre es die Anzahl der Zeichen mal zwei.

Die einzige Codierung, bei der wir (ab sofort) die Aussage über die Größe treffen können, ist UTF-32. Dort sind es immer 32 Bit pro Zeichen, obwohl ich mir vorstelle, dass Codepunkte für eine zukünftige UTF-64 vorbereitet sind :)

Was es so schwierig macht, sind mindestens zwei Dinge:

  1. zusammengesetzte Zeichen, bei denen ein Benutzer anstelle der bereits akzentuierten / diakritischen Zeichenentität (À) den Akzent und das Basiszeichen (`A) kombiniert.
  2. Codepunkte. Codepunkte sind die Methode, mit der die UTF-Codierungen mehr als die Anzahl der Bits codieren können, die ihnen normalerweise ihren Namen geben würden. Beispielsweise bezeichnet UTF-8 bestimmte Bytes, die für sich genommen ungültig sind. Wenn jedoch ein gültiges Fortsetzungsbyte folgt, kann ein Zeichen außerhalb des 8-Bit-Bereichs von 0..255 beschrieben werden. Siehe die Beispiele und überlangen Codierungen unten im Wikipedia-Artikel zu UTF-8.
    • Das dort angeführte hervorragende Beispiel ist, dass das € -Zeichen (Codepunkt U+20ACkann entweder als Drei-Byte- Sequenz E2 82 ACoder als Vier-Byte- Sequenz dargestellt werden F0 82 82 AC.
    • Beide sind gültig, und dies zeigt, wie kompliziert die Antwort ist, wenn von "Unicode" und nicht von einer bestimmten Codierung von Unicode wie UTF-8 oder UTF-16 gesprochen wird.
0xC0000022L
quelle
4

Nun, ich habe gerade auch die Wikipedia-Seite darauf aufgerufen und im Intro-Teil gesehen, dass "Unicode durch verschiedene Zeichencodierungen implementiert werden kann. Die am häufigsten verwendeten Codierungen sind UTF-8 (das ein Byte für alle ASCII-Zeichen verwendet, die diese haben) die gleichen Codewerte sowohl in der UTF-8- als auch in der ASCII-Codierung und bis zu vier Bytes für andere Zeichen), das mittlerweile veraltete UCS-2 (das zwei Bytes für jedes Zeichen verwendet, aber nicht jedes Zeichen im aktuellen Unicode-Standard codieren kann) "

Wie dieses Zitat zeigt, besteht Ihr Problem darin, dass Sie davon ausgehen, dass Unicode eine einzige Methode zum Codieren von Zeichen ist. Es gibt tatsächlich mehrere Formen von Unicode, und auch in diesem Zitat hat eine von ihnen sogar 1 Byte pro Zeichen, genau wie Sie es gewohnt sind.

Ihre einfache Antwort, die Sie wollen, ist also, dass sie variiert.

Loduwijk
quelle
3

Für UTF-16 benötigt das Zeichen vier Bytes (zwei Codeeinheiten), wenn es mit 0xD800 oder höher beginnt. Ein solches Zeichen wird als "Ersatzpaar" bezeichnet. Insbesondere hat ein Ersatzpaar die Form:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

Dabei gibt [...] eine Zwei-Byte-Codeeinheit mit dem angegebenen Bereich an. Alles <= 0xD7FF ist eine Codeeinheit (zwei Bytes). Alles> = 0xE000 ist ungültig (außer wohl Stücklistenmarkierungen).

Siehe http://unicodebook.readthedocs.io/unicode_encodings.html , Abschnitt 7.5.

vorbenetzen
quelle
1

Schauen Sie sich diesen Unicode-Code-Konverter an . Geben Sie beispielsweise in das Feld "0x ... Notation" ein 0x2009, wobei 2009 die Unicode-Nummer für Thin Space ist, und klicken Sie auf "Konvertieren". Die Hexadezimalzahl E2 80 89(3 Byte) wird im Feld "UTF-8-Codeeinheiten" angezeigt.

ma11hew28
quelle
1

Aus dem Wiki:

UTF-8, eine 8-Bit-Codierung mit variabler Breite, die die Kompatibilität mit ASCII maximiert;

UTF-16, eine 16-Bit-Codierung mit variabler Breite;

UTF-32, eine 32-Bit-Codierung mit fester Breite.

Dies sind die drei beliebtesten unterschiedlichen Codierungen.

  • In UTF-8 wird jedes Zeichen in 1 bis 4 Bytes codiert (die dominante Codierung).
  • In UTF16 wird jedes Zeichen in 1 bis 2 16-Bit-Wörter und codiert
  • In UTF-32 wird jedes Zeichen als einzelnes 32-Bit-Wort codiert.
Chikitin
quelle
0

Unicodeist ein Standard, der für jedes Zeichen eine eindeutige Nummer bereitstellt. Diese eindeutigen Zahlen werden code points (was nur ein eindeutiger Code ist) für alle auf der Welt vorhandenen Zeichen genannt (einige müssen noch hinzugefügt werden).

Für verschiedene Zwecke müssen Sie dies möglicherweise code pointsin Bytes darstellen (die meisten Programmiersprachen tun dies), und hier setzt ein Character Encoding.

UTF-8, UTF-16, UTF-32Und so weiter sind alle Character Encodings, und Unicode der Codepunkte werden in diesen Kodierungen, auf unterschiedliche Weise dargestellt.


UTF-8 Die Codierung hat eine Länge variabler Breite, und die darin codierten Zeichen können 1 bis einschließlich 4 Bytes belegen.

UTF-16hat eine variable Länge und darin codierte Zeichen können entweder 1 oder 2 Bytes (8 oder 16 Bit) aufnehmen. Dies stellt nur einen Teil aller Unicode-Zeichen dar, die als BMP (Basic Multilingual Plane) bezeichnet werden, und reicht für fast alle Fälle aus. Java verwendet die UTF-16Codierung für seine Zeichenfolgen und Zeichen.

UTF-32 hat eine feste Länge und jedes Zeichen benötigt genau 4 Bytes (32 Bit).

Giorgi Tsiklauri
quelle