Warum gibt es mehrere Unicode-Codierungen?

41

Ich dachte, Unicode wurde entwickelt, um das Problem der vielen unterschiedlichen Codierungen zu umgehen, da bei den meisten früheren Versuchen (ASCII usw.) nur ein kleiner Adressraum (8 Bit) zur Verfügung stand.

Warum gibt es dann so viele Unicode-Codierungen? Sogar mehrere Versionen des (im Wesentlichen) gleichen, wie UTF-8, UTF-16 usw.

Matthew Scharley
quelle
11
UTF-8 ist nicht dasselbe wie UTF-16. Die Liste wird wachsen, sobald wir auf andere Sonnensysteme mit erdähnlichen Planeten stoßen.
Setzamora
1
@Joset: Wir haben schon klingonisch. Wir haben die meisten Erdsprachen auf dem BMP mit leichtem Auslaufen in die Ebenen 1,2. Wenn die aktuellen Bedingungen korrekt sind und es nur 42 empfindungsfähige Arten in der Galaxie gibt, die einen Punkt erreichen, an dem sie die Raumfahrt nutzen können (so dass der erste Kontakt möglich ist), sollten wir in der Lage sein, alle Zeichen in allen Sprachen in UNICODE zu komprimieren (vorausgesetzt, wir können expandieren) 21 bis 22 Bit, um 64 Ebenen zu ermöglichen). Das lässt sogar 10 Bits Pufferraum, wenn wir die primitiven Spezies einbeziehen wollen, die keinen Raumflug erreicht haben.
Martin York
7
@ Kevin Hsu: UTF-7,8,16LE, 16BE, 32LE, 32BE. Es sind also mindestens 6 echte Codierungen vorhanden. UTF-9 und UTF-18 sind Aprilscherze.
MSalters
9
Das Gute an Standards ist, dass es so viele davon gibt
Homde
1
Sehen Sie, was Spolsky zu Unicode und Codierung zu sagen hat .
MPelletier

Antworten:

29

Weil die Leute nicht 21 Bits für jeden Charakter ausgeben wollen. Auf allen modernen Systemen würde dies im Wesentlichen bedeuten, drei Bytes pro Zeichen zu verwenden, was dreimal mehr ist als das, was die Leute gewohnt waren, so dass sie überhaupt nicht bereit waren, Unicode zu übernehmen. Es mussten Kompromisse gefunden werden: UTF-8 eignet sich z. B. hervorragend für englischen Text, da ältere ASCII-Dateien überhaupt nicht konvertiert werden müssen, aber für europäische Sprachen weniger nützlich und für asiatische Sprachen von geringem Nutzen sind.

Grundsätzlich hätten wir also eine einzige universelle Kodierung sowie eine einzige universelle Zeichentabelle definieren können, aber der Markt hätte dies nicht akzeptiert.

Kilian Foth
quelle
8
+1 Gute Antwort. Um ehrlich zu sein, ist es die einzige, die diese Frage wirklich beantwortet. Bei allen anderen Antworten geht es (mehr oder weniger) darum, wie Bytes in allen verschiedenen Unicode-Codierungen angeordnet sind.
Jacek Prucia
Historisch ist es eine einfache Sache der Meinungsverschiedenheit. Allerdings sehe ich heute für nichts anderes als UTF-8 eine große Verwendung, während es theoretische Szenarien gibt, in denen UTF-16 weniger Speicherplatz verbraucht, dies jedoch nicht mit großem Abstand der Fall ist und selten vorkommt. Der bekannteste Ort, an dem Sie Platz sparen möchten, sind Websites, die jedoch mit HTML-Codes gefüllt sind, die mit UTF-8 bei weitem am kürzesten sind. Sie könnten zum Beispiel Shift JISeine japanische Website kleiner als das UTF-8-Äquivalent machen, aber das funktioniert nur, weil es ein Zeichensatz speziell für Japanisch ist.
aaaaaaaaaaa
2
Auch nicht wirklich wahr. Da die komprimierten Formate eigentlich nur für Transport und Lagerung verwendet werden. In einer Anwendung ist es üblicher, UCS-2 oder UCS-4 zu verwenden, da diese eine feste Breite haben, jedoch 2 oder 4 Bytes pro Zeichen benötigen. Daher sind Anwendungen bereit, den Platz für die Benutzerfreundlichkeit aufzugeben.
Martin York
but it is less useful for European languages, and of little use for Asian languages- Das ist einfach falsch. Mit "Nützlichkeit" meinen Sie Komprimierung? Dann bietet UTF-8 eine bessere Komprimierung für europäische Sprachen, da in jedem Text Leerzeichen und Interpunktionszeichen enthalten sind, die nur ein einziges Byte benötigen.
Nick Volynkin
37

Unicode ist ein 21-Bit-Zeichen, das die eindeutig beschriebenen "CodePoints" codiert, wobei die einzelnen Codepunkte durch ein Symbol (eine grafische Darstellung) dargestellt werden.

  • 16 Bits zur Identifizierung eines Codepunkts in einer Ebene (die meisten Codepunkte befinden sich in Ebene 0).
  • 5 Bits zur Identifizierung der Ebene.

Die unterstützten Codierungen sind:

  • UTF-8 (um jeden Punkt mit 8-Bit-Werten zu codieren)
  • UTF-16 (um jeden Punkt mit 16-Bit-Werten zu codieren)
  • UTF-32 (um jeden Punkt mit 32-Bit-Werten zu codieren)

Unabhängig von der Codierung ordnen sie sich beim Decodieren alle einem bestimmten Codepunkt zu, der dieselbe Bedeutung hat (weshalb es cool ist).

UTF-8

Dies ist ein Format mit variabler Größe. Wobei jeder Codepunkt durch 1 bis 4 Bytes dargestellt wird.

UTF-16

Dies ist ein Format mit variabler Größe. Die Codepunkte in der "Mehrsprachigen Grundebene" (BMP oder Ebene 0) können durch 1 einzelnen 16-Bit-Wert dargestellt werden. Codepunkte in anderen Ebenen werden durch ein Ersatzpaar (2 16-Bit-Werte) dargestellt.

UTF-32

Dies ist ein Format mit fester Größe. Alle Codepunkte werden durch einen einzelnen 32-Bit-Wert dargestellt.

Martin York
quelle
2
Diese Antwort gefällt mir auch. Schreibte eine ähnliche, aber diese ist klar. Ich möchte auch hinzufügen, dass UTF-8 auch nützlich ist, wenn ASCII-Zeichenfolgen automatisch UTF-8 sind.
Kevin Hsu
4
Bitte, es ist das mehrsprachige Basisflugzeug , keine Ebene .
JSB ձոգչ
3
Dies ist eine gute Antwort, aber ich denke, es wirft immer noch die Frage "Warum?" Auf, obwohl diese Antwort implizit darauf eingeht. Um es näher zu erläutern: UTF-32 ist ein direkterer (von manchen als einfacher bezeichneter) Ansatz für die Codierung von Unicode-Zeichen, verschwendet jedoch auch viel Platz, da jedes einzelne Zeichen 4 Byte belegt. UTF-8 ist viel kompakter und abwärtskompatibler mit ASCII, aber es ist nicht normal: Die Kodierung eines Zeichens kann zwischen 1 und 4 Byte dauern, was die Arbeit erschwert. UTF-16 ist eine Art hybrider Ansatz zwischen beiden, meist mit den Vor- und Nachteilen der beiden.
mipadi
4
Es gibt einen Kompromiss zwischen der Speichernutzung (wo UTF-8 am besten ist, da die häufigsten Zeichen Einzelbyte sind) und der Verarbeitungsgeschwindigkeit (wo UTF-32 am besten ist, weil alle Zeichen die gleiche Größe haben, wodurch bestimmte Optimierungen möglich und perfekt sind 32-Bit-Ausrichtung im Speicher). Daher verwenden Netzwerkprotokolle und Dateiformate in der Regel UTF-8 (um Bandbreite / Speicherplatz zu sparen), während Skriptinterpreter und Sprachlaufzeiten UTF-16 oder UTF-32 bevorzugen.
tdammers
2
@Marcel: Ein "CodePoint" ist kein "CodePoint" character(ein Zeichen kann aus mehreren "CodePoints" bestehen). Verwechseln Sie die beiden Begriffe nicht. Aber Sie sind richtig. "CodePoints" beziehen sich nicht auf Glyphen. Eine Glyphe ist nur eine grafische Darstellung eines Codepunkts. Ein subtiler, aber wichtiger Unterschied.
Martin York
25

Ich denke, es ist nützlich, die beiden Ideen zu trennen:

  1. Unicode - Zuordnung von Zeichen aus aller Welt zu Codepunkten.
  2. Codierung - Zuordnung von Codepunkten zu Bitmustern (UTF-8, UTF-16 usw.).

UTF-8, UTF-16 und andere Kodierungen haben jeweils ihre eigenen Vor- und Nachteile. Wenden Sie sich dazu besser an Wikipedia .

jfs
quelle
@jfs: Warum überhaupt Unicode, wenn es immer noch ein Dutzend oder mehr verschiedene Codierungen geben wird, die auf der Leitung sowieso alle unterschiedlich sind? Welchen Nutzen hat ein globales Mapping für sich?
Matthew Scharley
10
@ Matthew Scharley: Du siehst es falsch. UNICODE ordnet alle Zeichen aus allen Sprachen (einschließlich Klingonisch) einer EINZIGARTIGEN ID (Codepunkt) zu. Die Codierungen sind lediglich eine Möglichkeit, die Codepunkte auf eine Disc oder einen Stream über ein Netzwerk zu komprimieren. UTF steht für "UNICODE Transport Format". Sie sollten sich einen UNICODE-Codepunkt immer als 21-Bit-Wert vorstellen. Der Vorteil gegenüber anderen Formaten ist, dass alle Zeichen eindeutig identifiziert werden und sich nicht überlappen (im Gegensatz zu Latin-1, Latin-2 usw.).
Martin York
@Matthew Scharley Warum ein globales Mapping? Eigentlich hatte jeder in der Vergangenheit sein eigenes Mapping (erinnerst du dich an Codeseiten?). Ich denke, ein albernes Beispiel wird die Dinge klären. Stellen Sie sich die Idee der Liebe vor. Wie werden Sie es jemandem vorstellen? Blumen geben? Sag "Ich liebe dich"? Jeder hat seine eigene Art, es auszudrücken. Liebe (was eine abstrakte Idee ist) ist wie die Codepunkte. Es auszudrücken ist wie die Kodierungen. :)
jfs
4
Unicode ist das globale Alphabet. UTF-x wird von Computern transportiert, da es schwierig ist, Papier durch Drähte zu schieben.
Mel
1
@ Martin, Klingonisch hat es tatsächlich nicht geschafft. Auch die Tengwar oder Cirith, mit denen Tolkeins Elfenzungen geschrieben wurden, kamen nicht in Frage.
TRiG
9

UTF-7, UTF-8, UTF-16 und UTF-32 sind einfach algorithmische Transformationsformate derselben Kodierung (Kodepunkte) von Zeichen. Sie sind Kodierungen eines Systems zur Kodierung von Zeichen.

Sie sind auch algorithmisch einfacher vorwärts und rückwärts zu navigieren als die meisten vorherigen Schemata für den Umgang mit Zeichensätzen, die größer als 256 Zeichen sind.

Dies unterscheidet sich stark von der landes- und manchmal herstellerspezifischen Kodierung von Glyphen. Alleine auf Japanisch gab es eine Menge Variationen von JIS, ganz zu schweigen von EUC-JP und der Codepage-orientierten Umwandlung von JIS, die DOS / Windows-Maschinen mit der Bezeichnung Shift-JIS verwendeten. (Bis zu einem gewissen Grad gab es algorithmische Transformationen von diesen, aber sie waren nicht besonders einfach und es gab herstellerspezifische Unterschiede in den verfügbaren Zeichen. Multiplizieren Sie dies mit ein paar hundert Ländern und der schrittweisen Entwicklung komplexerer Schriftsysteme (Post-Greenscreen) Ära), und Sie hatten einen echten Albtraum.

Warum brauchen Sie diese Transformationsformen von Unicode? Da viele ältere Systeme Sequenzen mit 7-Bit-Zeichen im ASCII-Bereich voraussetzten, brauchten Sie eine saubere 7-Bit-Lösung, mit der Daten sicher und fehlerfrei durch diese Systeme geleitet werden können. Dann brauchten Sie UTF-7. Dann gab es modernere Systeme, die mit 8-Bit-Zeichensätzen umgehen konnten, aber Nullen hatten im Allgemeinen eine besondere Bedeutung, sodass UTF-16 für sie nicht funktionierte. 2 Bytes könnten die gesamte mehrsprachige Grundebene von Unicode in ihrer ersten Inkarnation codieren, sodass UCS-2 für Systeme, die von Grund auf "Unicode-fähig" sein sollten (wie Windows NT und die Java-VM), als vernünftiger Ansatz erscheint. dann erforderten die Erweiterungen darüber hinaus zusätzliche Zeichen, was zur algorithmischen Transformation der 21-Bit-Codierungen führte, die durch den Unicode-Standard reserviert wurden, und es wurden Ersatzpaare geboren; das erforderte UTF-16. Wenn Sie eine Anwendung hatten, bei der die Konsistenz der Zeichenbreite wichtiger war als die Effizienz der Speicherung, war UTF-32 (früher als UCS-4 bezeichnet) eine Option.

UTF-16 ist das einzige Problem, mit dem man sich aus der Ferne befassen muss. Dies lässt sich durch die geringe Anzahl von Zeichen, die von dieser Transformation betroffen sind, und durch die Tatsache, dass die führenden 16-Bit-Sequenzen in einem völlig anderen Bereich liegen als die nachfolgenden 16-Bit-Sequenzen. Es ist auch um Welten einfacher, als in vielen frühen ostasiatischen Codierungen vorwärts und rückwärts zu gehen, in denen Sie entweder einen Zustandsautomaten (JIS und EUC) für die Verarbeitung der Escape-Sequenzen benötigen oder möglicherweise mehrere Zeichen zurücksetzen müssen, bis Sie etwas gefunden haben, das garantiert ist nur ein führendes Byte sein (Shift-JIS). UTF-16 hatte einige Vorteile auf Systemen, die auch 16-Bit-Sequenzen effizient durchlaufen konnten.

Man könnte meinen, es sei denn, man müsse Dutzende (Hunderte, wirklich) verschiedener Codierungen durchstehen oder Systeme bauen, die mehrere Sprachen in unterschiedlichen Codierungen unterstützen, manchmal sogar im selben Dokument (wie WorldScript in den älteren MacOs-Versionen) der Unicode-Transformationsformate als unnötige Komplexität. Gegenüber früheren Alternativen wird die Komplexität jedoch drastisch reduziert, und jedes Format löst eine echte technische Einschränkung. Sie sind auch wirklich effizient untereinander konvertierbar und erfordern keine komplexen Nachschlagetabellen.

JasonTrue
quelle
1
Die verschiedenen JIS- und EUC-Zustandsautomaten sind wirklich unangenehm, und das ist doppelt so schlimm, wenn Sie mit der Transformation zwischen ihnen arbeiten. Unicode vereinfacht das enorm. Das einzige große Problem mit Unicode ist , dass Sie haben bekommen zu stoppen Sie zu denken von Bytes als Zeichen, Sie ASCII-mit kleinen Zeichen-setted chauvinistischen Sie!
Donal Fellows
6

Unicode wurde nicht entwickelt, um das Problem der vielen verschiedenen Codierungen zu umgehen.

Unicode wurde entwickelt, um die gesamte Ausgabe einer Zahl zu umgehen, die je nach verwendeter Codepage viele verschiedene Dinge darstellt. Die Nummern 0 bis 127 stehen für die gleichen Zeichen in jeder Ansi-Codepage. Dies wird auch als ASCII-Diagramm oder Zeichensatz bezeichnet. In Ansi-Codepages, die 256 Zeichen zulassen, stehen die Nummern 128 bis 255 für verschiedene Zeichen in verschiedenen Codepages.

Zum Beispiel

  • Die Zahl $ 57 steht für ein W in Großbuchstaben in allen Codepages, jedoch
  • Die Zahl $ EC steht für das Inifinity-Symbol in Codepage 437 (USA), jedoch für einen "LATIN SMALL LETTER N WITH CEDILLA" in Codepage 775 (Baltikum).
  • Das Cent-Zeichen hat die Nummer $ 9B in Codepage 437, aber die Nummer 96 in Codepage 775

Was Unicode tat, war dies alles auf den Kopf zu stellen. In Unicode gibt es keine "Wiederverwendung". Jede Zahl steht für ein einzelnes Zeichen. Die Zahl $ 00A2 in Unicode ist das Cent-Zeichen und das Cent-Zeichen wird an keiner anderen Stelle in der Unicode-Definition angezeigt.

Warum gibt es dann so viele Unicode-Codierungen? Sogar mehrere Versionen des (im Wesentlichen) gleichen, wie UTF-8, UTF-16 usw.

Es gibt keine mehreren Versionen derselben Kodierung. Es gibt mehrere Codierungen derselben Unicode-Zeichendefinitionszuordnung, die "erfunden" wurden, um die Speicheranforderungen für unterschiedliche Verwendungen der verschiedenen in Unicode vorhandenen lingualen Ebenen zu verwalten.

Unicode definiert (oder hat den Raum, um zu definieren) 4.294.967.295 eindeutige Zeichen. Wenn Sie diese ohne algorithmische Konvertierungen auf den Platten- / Arbeitsspeicher abbilden möchten, benötigen Sie 4 Bytes pro Zeichen. Wenn Sie Texte mit Zeichen aus allen Sprachebenen speichern müssen, ist UTF-32 (im Grunde genommen eine direkte 1-Zeichen- 4-Byte-Speicherkodierung der Unicode-Definition) wahrscheinlich das Richtige für Sie.

In kaum einem Text werden Zeichen aus allen Sprachen verwendet. Und dann scheint die Verwendung von 4 Bytes pro Zeichen eine große Verschwendung zu sein. Insbesondere, wenn Sie berücksichtigen, dass die meisten Sprachen auf der Erde in der sogenannten mehrsprachigen Grundebene (BMP) definiert sind: den ersten 65536-Zahlen der Unicode-Definition.

Und genau hier kam UTF-16 ins Spiel. Wenn Sie nur Zeichen aus dem BMP verwenden, speichert UTF-16 dies sehr effizient mit nur zwei Bytes pro Zeichen. Es werden nur mehr Bytes für Zeichen außerhalb des BMP verwendet. Die Unterscheidung zwischen UTF-16LE (Little Endian) und UTF-16BE (Big Endian) hat wirklich nur etwas damit zu tun, wie Zahlen im Computerspeicher dargestellt werden (Byte-Muster A0bedeutet hex $ A0 oder $ 0A).

Wenn Ihr Text noch weniger verschiedene Zeichen enthält, wie die meisten Texte in westeuropäischen Sprachen, möchten Sie die Speicheranforderungen für Ihre Texte noch weiter einschränken. Daher UTF-8, das ein einzelnes Byte zum Speichern der im ASCII-Diagramm vorhandenen Zeichen (die ersten 128 Ziffern) und eine Auswahl aus den Ansi-Zeichen (die zweiten 128 Ziffern der verschiedenen Codepages) verwendet. Es werden nur mehr Bytes für Zeichen außerhalb dieses "am häufigsten verwendeten Zeichensatzes" verwendet.

Um es noch einmal zusammenzufassen:

  • Unicode ist eine Zuordnung der Zeichen in allen Sprachen der Erde (und einige klingonische, um zu starten) und einige (mathematisch, musikalisch usw.) zu einer eindeutigen Zahl.
  • Codierungen sind Algorithmen, die definiert wurden, um Texte unter Verwendung der Nummern dieser eindeutigen Zeichentabelle so platzsparend wie möglich zu speichern, wenn die "durchschnittliche Verwendung" von Zeichen in Texten gegeben ist.
Marjan Venema
quelle
2
"Die Zahlen 0 - 127 stehen für die gleichen Zeichen in jeder Codepage." - na ja, es sei denn , Sie sprechen EBCDIC, wobei in diesem Fall $57ist kein W
MSalters
@MSalters: du hast absolut recht. EBCDIC ist anders (und es gibt andere EBCDIC). Ich schätze, meine Mainframe-Tage sind so lange hinter mir, dass ich mich nicht mehr daran erinnere, oder ich habe diese Erinnerungen zu hart und zu lange unterdrückt ... :-)
Marjan Venema
"Die Zahlen 0 - 127 stehen für die gleichen Zeichen in jeder Codepage." Es gibt tatsächlich Codierungen wie BinarySignWriting, bei denen es sich nicht um Obermengen von ASCII handelt. Tatsächlich enthält BinarySignWriting überhaupt keine ASCII-Zeichen.
TRiG
@TRiG: Aus diesem Grund habe ich meine Aussage so bearbeitet, dass sie sich speziell mit Ansi-Codepages befasst. Muss das getan haben, bevor Sie sich erfrischt haben ...
Marjan Venema
Ja. Während ich meinen Kommentar schrieb, gab es einen zusätzlichen Kommentar und ein Post-Update. Trotzdem ist BinarySignWriting interessant.
TRiG
2

Unicode definiert die Zuordnung zwischen Zahlen und Zeichen. Wenn Sie jedoch eine Nummer an einen Empfänger senden, müssen Sie noch definieren, wie diese Nummer dargestellt werden soll. Dafür ist UTF da. Es definiert, wie eine Zahl in einem Byte-Stream dargestellt wird.

Kodismus
quelle
2

Das Grundprinzip von UTF-32 ist einfach: Es ist die einfachste Darstellung von Unicode-Codepunkten. Warum ist nicht alles in UTF-32? Zwei Hauptgründe:

Eins ist Größe . UTF-32 benötigt 4 Bytes für jedes Zeichen. Bei Text, der nur Zeichen an der Basis-Mehrsprachigkeit verwendet, ist dies doppelt so viel Speicherplatz wie bei UTF-16. Für englischen Text ist der Platz viermal so groß wie für US-ASCII.

Der größere Grund ist die Abwärtskompatibilität . Jede andere Unicode-Codierung als die "nicht codierte" UTF-32-Codierung wurde aus Gründen der Abwärtskompatibilität mit einem früheren Standard entwickelt.

  • UTF-8: Abwärtskompatibilität mit US-ASCII.
  • UTF-16: Abwärtskompatibilität mit UCS-2 (16-Bit-Unicode, bevor es über das BMP hinaus erweitert wurde).
  • UTF-7: Abwärtskompatibilität mit nicht 8-Bit-bereinigten Mailservern.
  • GB18030: Abwärtskompatibilität mit den Kodierungen GB2312 und GBK für Chinesisch.
  • UTF-EBCDIC: Abwärtskompatibilität mit der Basic Latin-Teilmenge von EBCDIC.

Ich dachte, Unicode wurde entwickelt, um das Problem der vielen verschiedenen Codierungen zu umgehen

Es war und es tat. Es ist viel einfacher, zwischen UTF-8, -16 und -32 zu konvertieren, als mit dem alten System von Hunderten verschiedener Zeichenkodierungen für verschiedene Sprachen und verschiedene Betriebssysteme umzugehen.

dan04
quelle
1

Sie wissen, dass eine Zip-Datei eine Datei so komprimieren kann, dass sie viel kleiner ist (insbesondere Text), und diese dann zu einer identischen Kopie der Originaldatei dekomprimieren kann.

Der Zipping-Algorithmus verfügt tatsächlich über mehrere verschiedene Algorithmen mit verschiedenen Merkmalen zur Auswahl: gespeichert (keine Komprimierung), verkleinert, verkleinert (Methoden 1 bis 4), implodiert, Tokenisieren, entleert, entleert64, BZIP2, LZMA (EFS), WavPack, PPMd, wo es theoretisch alle versuchen und das beste Ergebnis wählen könnte, aber normalerweise einfach mit Entleert gehen.

UTF funktioniert ähnlich. Es gibt mehrere Codierungsalgorithmen mit jeweils unterschiedlichen Merkmalen, aber Sie wählen in der Regel nur UTF-8, da es im Gegensatz zu den anderen UTF-Varianten weitgehend unterstützt wird, was wiederum darauf zurückzuführen ist, dass es bitweise mit 7-Bit-ASCII kompatibel ist, was es einfach macht Verwendung auf den meisten modernen Computerplattformen, die normalerweise eine 8-Bit-Erweiterung von ASCII verwenden.


quelle
Anmerkung: Der Unterschied zu einer ZIP-Datei besteht darin, dass ein Header angibt, welche Komprimierung wirksam ist. Bei Textdateien müssen wir immer noch raten, nicht wahr?
Matthew Scharley
Es gibt eine spezielle Sequenz, die genau das sagt. Aufgrund der Abwärtskompatibilität mit ASCII ist dies optional.