Tips für Web-Profis (Designer & HTML-Autoren)

Zeichenkodierung Teil II - UTF-8

Einstimmung zum Thema Informationseinheiten

Eine typische Informationseinheit in der Mathematik ist die Ziffer. Sie kann 10 verschiedene Zustände darstellen (Werte haben), nämlich 0, 1, 2, 3, 4, 5, 6, 7, 8 oder 9.

In der englischen Sprache ist der Buchstabe eine Informationseinheit, die 48 verschiedene Zustände annehmen kann, nämlich a, b, c, d, ..., z, A, B, C, D, ..., Z.

In der Logik (auch Mathematik) gibt es, als Antwort auf Aussagen, eine Informationseinheit, die nur zwei mögliche Werte zulässt: wahr oder falsch.

Die Informationseinheit der digitalen Elektronik kennt auch nur zwei Zustände: Strom oder kein Strom.

Da die Werte der elektronischen Datenverarbeitung (EDV) letzten Endes in die digitale Elektronik überführt werden, gibt es in der EDV eine Informationseinheit, die der vorgenannten entspricht und durch diese dargestellt wird. Man nennt sie das Bit. Ein Bit kann auch nur zwei Werte haben: 0 oder 1.

Aus aneinandergereihten Bits setzt man in der EDV alle größeren Informationseinheiten zusammen. So auch die Informationseinheit Byte. Für ein Byte reiht man einfach acht Bit aneinander. Jedes dieser Bits kann die Werte 0 oder 1 annehmen. Daraus ergeben sich 256 verschiedene Werte, die ein Byte repräsentieren kann.

BinärZahlenwert
000000000
000000011
000000102
000000113
000001004
000001015
......
11111111255

Unklar? Macht nichts! Das einzige, was man wissen muss, ist: Ein Byte kann 256 verschiedene Werte repräsentieren.

Im Normalfall speichert mein Editor die Buchstaben als Zahlenwerte. Wenn ich ein A schreibe, dann ist das fúr den Computer das ASCII-Zeichen mit der Kennzahl 65. Er speichert und verarbeitet letzten Endes ein Byte mit dem Wert 65 bzw. mit den Bits 010000001, die sich von der darunterliegenden Elektronik darstellen lassen.

Für das Funktionieren des Informationsaustauschs müssen Sender und Empfänger der Information (mein Editor und Dein Browser) sich nur darüber einig sein, dass jetzt ASCII-Text kommt und dass daher die Zahl 65 für den Buchstaben A steht.

Unicode-Zeichensatz

Unicode liegt ein Zeichensatz mit mehr als 100.000 Zeichen zugrunde. Diese sind durchnummeriert als Unicode-Punkte, z.B. steht U+0041 für den Buchstaben A. U+ besagt, dass der folgende Wert als Unicode-Punkt zu lesen ist und die 0041 ist die hexadezimale Darstellung der laufenden Nummer. In das Dezimalsystem umgerechnet ergibt die Nummer 0041 die Zahl 65. Es ist kein Zufall, dass auch in ASCII die 65 für den Buchstaben A steht: Die Unicode-Punkte U+0000 bis U+007F (also 0 bis 127) korrespondieren mit den 127 Zeichen des ASCII-Zeichensatzes.

Unicode-Zeichenkodierung

Wie im ersten Teil erwähnt, weisen die klassischen Zeichenkodierungen (z.B. ISO 8859-...) einem Zeichen ein Byte zu. Bytes können insgesamt 256 verschiedene Werte annehmen (die Werte von 0 bis 255). Daher können diese Kodierungen nur Zeichensätze mit insgesamt maximal 256 Zeichen abbilden. Das ist zu wenig, um alle Unicode-Punkte zu kodieren.

Nun ist es ja aber kein Muss, dass nur ein Byte verwendet wird, um ein Zeichen zu übertragen. Man kann ja auch einen Standard definieren, bei dem pro Zeichen zwei Bytes verwendet werden. Dann werden die Text-Dateien oder Datenmengen zwar doppelt so groß, aber man bekommt in diesem Zeichensatz wesentlich mehr Zeichen unter. Jeder der 256 Werte, die das erste Byte annehmen kann, kann mit jedem der Werte, die das zweite Byte annehmen kann, kombiniert werden. Daraus ergeben sich 256 x 256 = 65536 verschiedene Werte.

Wichtig ist nur, dass das Gerät oder Programm, mit dem die Information gelesen wird, auch versteht, welches Zeichen sich z.B. mit dem Wert 12380 gemeint ist. Solange Sender (z.B. Editor) und Empfänger (z.B. Browser) die gleiche Kodierung unterstützen ist es egal wie diese aufgebaut ist.

Zeichenkodierungen mit zwei Bytes pro Zeichen gibt es, und zwar heißen sie UCS‑2 (die 2 steht für zwei Bytes pro Zeichen) und UTF‑16 (hier steht die 16 steht für 16 Bit, was wiederum der Länge von zwei Bytes entspricht). UTF‑16 gibt es in zwei Varianten, UTF‑16LE und UTF‑16BE, was uns aber hier nicht interessiert.

Mit diesen auf zwei Bytes pro Zeichen basierenden Kodierungen werden die Dateien bzw. die im Netzwerk zu übertragenden Zeichenketten (Email etc.) doppelt so groß wie in den klassischen Koderiungen. Im Gegenzug hat man aber keine Probleme mit dem scharfen S oder dem griechischen Alphabet.

Das größere Datenvolumen ist ein Nachteil, aber es gibt noch einen: Wer glaubt, 65536 verschiedenen Zeichen müssten doch für alle Sprachen und Sonderzeichen ausreichen, hat vielleicht die Schriftzeichen der asiatischen Sprachen sowie etliche (für manche Leute) sehr nützliche Sonderzeichen und graphische Symbole vergessen.

Aber es gibt auch noch UTF‑32, in welchem für jedes Zeichen ganze vier Bytes zur Kodierung benutzt werden. Daraus ergeben sich Milliarden möglicher Zeichen. Nur werden die Dateien oder zu übertragenden Zeichenketten gleich gleich viermal so groß als bei klassischen Ein-Byte-Kodierungen. Dabei ist es egal, ob es sich um einen chinesischen Text oder um einen englischen Text ohne besondere Zeichen handelt: Jedes Zeichen kostet vier Bytes.

Kodierungen, bei denen jedes Zeichen durch mehrere Bytes dargestellt wird, vergrößern die Datenmengen also unnötigerweise.

Ein weiterer Nachteil von UTF‑16 und UTF‑32 ist, dass sie nicht kompatibel mit älteren Kodierungen sind. Während bei den Klassikern die ersten 127 Zeichen immer gleich waren, bestehen auch diese ja jetzt aus zwei bzw. vier Bytes.

Die Rettung: UTF-8

Ken Thompson und Rob Pike haben alle obengenannten Probleme für uns bereits 1992 gelöst, indem sie UTF‑8 erfunden haben.

Das Prinzip geht so: Die „normalen Zeichen” werden durch ein Byte dargestellt und die „ausgefalleneren” durch mehrere Bytes.

Die Zeichen des ASCII-Kodes werden exakt wie bei ASCII (und praktisch allen klassischen Kodierungen wie Latin‑1 etc.) mittels eines einzelnen Bytes dargestellt. Die Werte dieser Zeichen entsprechen genau den ASCII-Werten von 0 bis 127. Damit kann ein Programm, welches UTF‑8 verarbeitet, auch ganz normale ASCII-Dateien und -Zeichenketten lesen und schreiben. Kompatibilitätsproblem gelöst.

Wenn ein Byte einen höheren Wert als 127, dann ist es Teil eines Mehr-Byte-Zeichens (engl. Multibyte Characters). Wieviele Bytes dieses Zeichen dann tatsächlich hat, ergibt sich daraus, in welchem Bereich dieses erste Byte liegt. Liegt der Wert des ersten Bytes zwischen 192 und 223, dann besagt das, dass wir uns am Anfang eines Zwei-Byte-Zeichens befinden. Es wird also das Zeichen dargestellt, was sich aus diesem ersten und dem nächsten Byte ergibt. Liegt der Wert eines Bytes zwischen 224 und 239, so läutet es ein Drei-Byte-Zeichen ein. Es wird also das Zeichen dargestellt, welches sich aus diesem ersten und den folgenden zwei Bytes ergibt. Entsprechend gibt es auch Bereiche für Zeichen, die durch vier bis acht Bytes repräsentiert werden.

Konsequenz: Nur für spezielle Zeichen außerhalb des ASCII-Bereichs braucht man mehrere Bytes. Ein Text mit 1000 Buchstaben des Standard-Alphabets, in dem lediglich ein Nicht-ASCII-Zeichen vorkommt (nehmen wir das scharfe S) wird 1001 Byte lang sein: 999 Zeichen werden durch je ein Byte dargestellt und für das scharfe S werden zwei benötigt.

Und es hat BOM gemacht

Beim Speichern von Dateien in Unicode-Kodierungen fügen viele Programme an den Anfang der Datei eine Markierung ein, die angibt, um welche Art der Kodierung es sich handelt. Diese Markierung heißt BOM; das steht für Byte Order Mark.

In UTF-8-kodierten Webseiten sollte man die BOM tunlichst vermeiden. Wenn eine Seite oben links irgendwelchen Unfug anzeigt, könnte es sich um eine BOM handeln. Das kann man mit einem Hex-Editor überprüfen und ggf. auch korrigieren. Die Arbeit mit einem Hex-Editor würde den Rahmen dieser Einleitung sprengen, aber für alle, die sich damit auskennen: Die BOM für UTF-8 besteht aus drei Bytes mit den folgenden Werten:
0xEF 0xBB 0xBF

Aber im Prinzip sollte es reichen, den Editor so zu konfigurieren, dass er eben UTF-8 kodiert und dieses ohne BOM abspeichert.

Hinweis zu Web-Formularen

Eingabefelder in Web-Formularen benutzen in der Regel die Kodierung der sie enthaltenden Seite. Man sollte sich allerdings nicht darauf verlassen. Sicherer ist es, dem Formular (dem FORM-Tag) das Attribut „accept‑charset” mitzugeben, also:
<form action="form_action.asp" accept-charset="utf-8">

Fazit

© Hermann F., 2010

Valid XHTML 1.0 Strict