Mehr über das Makeover für das SELF-Wiki im SELF-Blog!

Zeichencodierung/Unicode

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Der universale Code: Unicode[Bearbeiten]

Mit Unicode werden so ziemlich alle Zeichencodierungsprobleme dieser Welt gelöst. Und weil Webseiten potentiell mit allen Schriften dieser Welt genutzt werden, ist für HTML 4.0 und XML (und damit auch XHTML) festgelegt, dass grundsätzlich alle in Unicode definierten Zeichen vorkommen dürfen.

Mit dieser Festlegung kann man also jedes der mittlerweile über 100.000 Unicode-Zeichen in seinem Text verwenden. Aber Unicode regelt nicht nur die Codierung aller Schriftzeichen dieser Welt, sondern kennt zu jedem Zeichen dutzende definierte Eigenschaften. Ein Zeichen besitzt mindestens folgende Informationen:

  • der eindeutige Unicode-Name des Zeichens
  • den zugeordneten Codepoint (die „Nummer“ des Zeichens)
  • eine generelle Kategorisierung (Buchstabe, Zahl, Symbol, Interpunktion, ...)
  • weitere grundsätzliche Charakteristiken (Whitespace, Bindestrich, alphabetisch, ideografisch, Nicht-Zeichen, veraltet, ...)
  • anzeigerelevante Informationen (Schreibrichtung, Form, Spiegelung, Breite)
  • Groß-/Kleinschreibung
  • Zahlenwert und -typ bei Zahlzeichen
  • Trennfunktionen (zwischen Wörtern, Zeilen, Sätzen,...)
  • usw.

Die meisten Eigenschaften eines Zeichens sind nur für die interne Behandlung durch den Computer relevant. Beispielsweise werden arabische Schriftzeichen automatisch korrekt von rechts nach links geschrieben, oder der Zeilenumbruch nutzt die Stellen, an denen eine Wortgrenze z. B. durch ein normales Leerzeichen existiert. Dieser kleine Exkurs soll aber verdeutlichen, dass die Bytewerte der Buchstaben für den Computer viel mehr bedeuten können, als nur den Buchstaben an sich.

Über die Definition von Zeichen und ihren Codepoints hinaus liefert das Unicode-Consortium noch eine Fülle von weiteren Standardisierungen, die sich auf die linguistisch korrekten Behandlung von schriftlicher menschlicher Sprache beziehen. Darunter sind Algorithmen zur sprachspezifischen Sortierung (Beispiel: Im Deutschen gibt es zwei Sortierungsvarianten, Wörterbücher sortieren mit ä=a, ö=o, ü=u, Telefonbücher mit ä=ae, ö=oe, ü=ue) und zur Normalisierung (Wie prüft man, ob zwei Zeichenketten identisch sind).

Codierungsformen von Unicode-Zeichen[Bearbeiten]

Der oben erwähnte Codepoint eines Unicode-Zeichens ist nur eine abstrakte Nummer. Die Schreibweise dieser Nummer im Unicode-Standard erfolgt in hexadezimalen Zahlen mit vorangestelltem „U+“. Der Codepoint legt noch keinerlei computerkompatible Darstellung fest, dies ist Aufgabe des Codierschemas. Da die Unicode-Codepoints von U+0000 bis U+10FFFF (hexadezimale Zahlendarstellung), mit einer beabsichtigten Lücke zwischen U+D7FF und U+E000, reichen, sind für eine vollständige Codierung des gesamten Codepoint-Bereichs als Binärzahl mindestens 3 Byte erforderlich.

Im Folgenden werden die verbreiteten Speichervarianten von Unicode-Zeichen kurz vorgestellt.

UTF-32: Simpel, aber verschwenderisch[Bearbeiten]

Da Computer viel besser mit Vielfachen von 2 umgehen können, hat man kein Codierschema mit 3 Bytes definiert, sondern als simpelste Variante UTF-32 festgelegt, bei dem jede Codeeinheit 32 Bit = 4 Bytes groß ist. Der Codepoint jedes Zeichens wird hierbei einfach als 32-Bit-Zahlwert gespeichert.

Es gibt von UTF-32 zwei Varianten, UTF-32LE (Little Endian) und UTF-32BE (Big Endian), die sich einfach nur in der Reihenfolge unterscheiden, mit denen einzelne Bytes einer größeren Zahl in den Datenstrom gegeben werden. Big Endian beginnt mit der „Tausenderstelle“, Little Endian mit der „Einerstelle“. Damit eindeutig festgestellt werden kann, welche Variante genutzt wird, gibt es ein spezielles Zeichen namens „BOM“ (Byte Order Mark) mit dem Codepoint U+FEFF, welches dem Datenstrom vorangestellt wird. Sind die ersten vier Bytes eines Datenstroms 0x00, 0x00, 0xFE und 0xFF, so wird Big Endian verwendet. Sind es hingegen 0xFF, 0xFE, 0x00 und 0x00, wird Little Endian verwendet.

Der größte Nachteil ist, dass UTF-32 extrem verschwenderisch mit Speicherplatz umgeht. Da Unicode insgesamt pro Zeichen nur 3 Byte benötigt, ist pro UTF-32-Zeichen schon mindestens ein Byte ungenutzt verschwendet. Die am häufigsten benutzten Zeichen lassen sich sogar allesamt mit nur 2 Bytes darstellen, da sie sich im Bereich U+0000 bis U+FFFF befinden. Lateinische Buchstaben ohne diakritische Zeichen, wie sie in (westlichen) Fließtexten häufig vorkommen, lassen sich gar nur mit einem Byte codieren, da sie im Bereich U+0000 bis U+00FF vorkommen.

UTF-16: Praxisformat im RAM[Bearbeiten]

UTF-16 nutzt Codiereinheiten, die 16 Bit = 2 Bytes groß sind. Dies halbiert bei üblichen Texten den Speicherverbrauch im Vergleich zu UTF-32. Allerdings ließen sich mit nur 2 Bytes nicht mehr alle Unicode-Zeichen direkt darstellen. An dieser Stelle kommt die eingangs erwähnte beabsichtigte Lücke ins Spiel. Zeichen, die sich nicht direkt codieren lassen, weil sie aus dem Codepoint-Bereich zwischen U+10000 und U+10FFFF kommen, werden als Kombination zweier Codiereinheiten dargestellt, die aus dem Bereich U+D800 bis U+DFFF kommen. Da in diesem Bereich keine gültigen Unicode-Zeichen liegen können, kann ein Programm eindeutig erkennen, dass hier Zeichen aus dem höheren Bereich codiert wurden.

Auch für UTF-16 gibt es wieder die zwei Varianten UTF-16LE und UTF-16BE. Die BOM erscheint bei Big Endian als 0xFE, 0xFF, und bei Little Endian als 0xFF, 0xFE.

UTF-16 wird von vielen Programmen für die interne Repräsentation von Zeichenketten verwendet. Da es aber gerade bei westeuropäischen Sprachen immer noch relativ viele Bytes verschwendet, und außerdem Probleme mit Unicode-unfähigen Programmen wie z. B. Editoren macht, wird es zum Datenaustausch zwischen Systemen nicht sehr häufig verwendet.

UTF-8: Die Codierungsform der Wahl[Bearbeiten]

UTF-8 nutzt Codiereinheiten, die 8 Bit = 1 Byte groß sind. Genau wie bei UTF-16 ist der Gesamtbereich der Unicode-Zeichen mit nur einem Byte nicht abzudecken, also werden bei Bedarf mehrere Bytes zusammengefasst, um einen Codepoint zu codieren.

UTF-8 hat im Vergleich zu den anderen UTF-Varianten mehrere praktische Vorteile:

  • Die ersten 127 Zeichen und Bytes sind identisch mit ASCII, d. h. alle Texte, die in der Hauptsache Unicode-Zeichen mit Codepoints zwischen U+0000 und U+007F verwenden, bleiben problemlos lesbar.
  • Auch Systeme, die UTF-8 nicht verstehen, können die Bytes trotzdem (eingeschränkt) verarbeiten, weil es sich um – wenn auch eher abstruse – „normale“ Zeichen handelt.
  • Selbst das byteorientierte Sortieren von UTF-8-Texten funktioniert und sortiert die Strings geordnet nach dem Zahlenwert der enthaltenen Codepoints.
  • Bei Verwendung von westeuropäischen Sprachen wird im Vergleich zu UTF-16 viel Speicherplatz gespart, da die meisten Zeichen nur ein Byte benötigen.

Ein Unicode-Zeichen kann in UTF-8 zwischen einem und vier Bytes groß sein. Um einen Codepoint in UTF-8 zu codieren, wird dessen binäre Zahldarstellung benötigt.

Unicode-Bereich Binäre Zahldarstellung 1. Byte 2. Byte 3. Byte 4. Byte
U+0000–U+007F          00000000 0xxxxxxx 0xxxxxxx
U+0080–U+07FF          00000yyy yyxxxxxx 110yyyyy 10xxxxxx
U+0800–U+D7FF, U+E000–U+FFFF          zzzzyyyy yyxxxxxx 1110zzzz 10yyyyyy 10xxxxxx
U+10000–U+10FFFF 000uuuuu zzzzyyyy yyxxxxxx 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx

In der Tabelle steht u für die Angabe der Unicode-Ebene (Plane) falls nicht BMP. Was die Position des Zeichens innerhalb der Ebene betrifft, steht x steht für den Anteil im letzten, y für den Anteil im vorletzten und z für den Anteil im drittletzten Zeichen. Die Angabe anderer Unicode-Ebenen als der BMP muss auf die genannte Art erfolgen. Die UTF-16-Surrogates U+D800–U+DFFF dürfen nicht in UTF-8 kodiert werden. Einige Datenbanksysteme tun dies trotzdem. Diese Fehlfunktion wurde nachträglich als CESU-8 standardisiert. Ebenso ist die Codierung der Zeichen U+110000–U+1FFFFF oder die Erweiterung auf mehr als 4 Zeichen nicht erlaubt, da Unicode nur 17 Ebenen definiert und UTF-16 auch nur diese kodieren kann. Außerdem dürfen keine Sequenzen kodiert werden, die länger als nötig sind.

Ein Beispiel: Das Eurozeichen hat den Codepoint U+20AC. Die binäre Darstellung dieser Zahl ist 00100000 10101100. Setzt man diese Bits in das Schema der dritten Zeile, so erhält man 11100010 10000010 10101100 oder als Bytes 0xE2, 0x82 und 0xAC.

UTF8Kodierung.png

UTF-8 basiert zwar prinzipiell auf Big Endian, kennt aber offiziell keine Varianten für Big Endian oder Little Endian. Die für diesen Zweck benutzte Byte Order Mark sieht immer gleich aus: 0xEF, 0xBB und 0xBF. Da sie somit ihren Zweck der Erkennung der Byte-Reihenfolge nicht erfüllt, darf man sie ohne Probleme weglassen. Allerdings kann sie auch zur Erkennung, dass es sich um UTF-8-Text handelt, herangezogen werden.