Zeichenkodierung, ASCII und UTF
Problem
Du speicherst den Namen „Müller“ in einer Datei, aber eine andere Anwendung zeigt „Müller“ an. Die Anwendungen interpretieren dieselben Bytes nach unterschiedlichen Regeln.
Lösung
1. Kodierung verbindet Text und Bytes
Dateien und Netzwerknachrichten speichern Bytes. Eine Zeichenkodierung legt fest, wie Text in diese Bytes umgewandelt wird. Beim Kodieren entsteht aus Text eine Bytefolge; beim Dekodieren wird daraus wieder Text.
Die schreibende und die lesende Anwendung müssen dieselbe Kodierung verwenden.
2. ASCII deckt einfache englische Texte ab
ASCII steht für American Standard Code for Information Interchange. Es definiert 128 Werte für englische Buchstaben, Ziffern, Satzzeichen und Steuerzeichen wie einen Zeilenumbruch.
A hat zum Beispiel den Wert 65, in hexadezimaler Schreibweise 41. Hexadezimal ist eine Zahlendarstellung zur Basis 16 mit 0–9 und A–F. ASCII verwendet sieben Bits, die üblicherweise in einem Byte gespeichert werden. Für ü, 日 oder Emojis gibt es in ASCII keine Darstellung.
3. Unicode gibt Zeichen eindeutige Kennungen
Unicode weist Zeichen Kennungen zu, die Codepunkte heißen. Das Zeichen ü hat zum Beispiel den Codepunkt U+00FC. Das Präfix U+ kennzeichnet einen Unicode-Codepunkt; 00FC ist seine Nummer in hexadezimaler Schreibweise.
Ein Codepunkt identifiziert das Zeichen. Eine Kodierung legt fest, welche Bytes es in einer Datei darstellen.
4. UTF-8 wandelt Codepunkte in Bytes um
UTF bedeutet Unicode Transformation Format. UTF-8 stellt Unicode-Codepunkte mit einem bis vier Bytes dar. Die „8“ steht für 8-Bit-Einheiten und beschreibt keine feste Größe für jedes Zeichen.
Jede Zeile zeigt das Zeichen, seinen Codepunkt und seine UTF-8-Bytes:
A → U+0041 → 41 (1 Byte) ü → U+00FC → C3 BC (2 Bytes) 日 → U+65E5 → E6 97 A5 (3 Bytes) 😀 → U+1F600 → F0 9F 98 80 (4 Bytes)
Jedes Paar wie C3 steht für ein Byte in hexadezimaler Schreibweise. UTF-8 übernimmt die ASCII-Werte: A wird in beiden Kodierungen als 41 gespeichert.
5. Schritt für Schritt: Von 😀 zu gespeicherten Bytes und zurück
Schritt 1 — Eine Nummer zuweisen. Das Unicode-Konsortium hat dem Zeichen 😀 mit dem Namen GRINNING FACE die Nummer 128512 zugewiesen. Diese zugewiesene Nummer ist sein Unicode-Codepunkt.
Schritt 2 — Die Nummer hexadezimal schreiben. Die Dezimalzahl 128512 lautet hexadezimal 1F600. Das sind zwei Schreibweisen derselben Zahl.
Schritt 3 — Die Unicode-Schreibweise verwenden. Wir schreiben den Codepunkt als U+1F600. Das Präfix U+ zeigt an, dass es sich um einen hexadezimal geschriebenen Unicode-Codepunkt handelt; es fügt keinen Zahlenwert hinzu.
Schritt 4 — Für die Speicherung kodieren. UTF-8 kodiert diesen Codepunkt in vier Bytes. Die Bytewerte zeigen wir hexadezimal als F0 9F 98 80 an. U+1F600 ist die Kennung des Zeichens; F0 9F 98 80 ist seine UTF-8-Bytefolge.
Jedes Byte ist eine 8-Bit-Einheit. Hier sind dieselben vier Bytes in Binärschreibweise:
F0 → 11110000 → 8 Bits 9F → 10011111 → 8 Bits 98 → 10011000 → 8 Bits 80 → 10000000 → 8 Bits
UTF-8 speichert 😀 also mit vier Bytes oder 32 Bits. Die 8 in UTF-8 steht für die 8-Bit-Einheiten. Ein Zeichen kann mehrere dieser Einheiten benötigen.
Schritt 5 — Lesen und anzeigen. Ein UTF-8-Dekoder liest die vier Bytes gemeinsam und rekonstruiert den Codepunkt U+1F600, also dezimal 128512. Die Anwendung verwendet anschließend eine Schriftart, um 😀 anzuzeigen.
6. Warum aus „Müller“ plötzlich „Müller“ wird
In UTF-8 besteht der hier gezeigte Name aus diesen Bytes:
Müller → 4D C3 BC 6C 6C 65 72
Ein UTF-8-Leser interpretiert C3 BC gemeinsam als ü. Ein Windows-1252-Leser interpretiert sie einzeln als à und ¼. So entsteht „Müller“.
Wähle beim Import einer als UTF-8 gespeicherten CSV-Datei ebenfalls UTF-8 in den Importeinstellungen. Bei verstümmeltem Text prüfst du die Kodierung der Originaldatei und öffnest sie damit erneut, bevor du Änderungen speicherst.
7. Wofür UTF-16 und UTF-32 stehen
UTF-8, UTF-16 und UTF-32 können denselben Unicode-Text darstellen. Sie verwenden unterschiedliche Speichereinheiten:
UTF-8: ein bis vier Bytes pro kodiertem Codepunkt.
UTF-16: eine oder zwei 16-Bit-Einheiten, also zwei oder vier Bytes.
UTF-32: eine 32-Bit-Einheit, also vier Bytes.
Für neue Textdateien und Webdaten ist UTF-8 eine sinnvolle Standardwahl. Verwende eine andere Kodierung, wenn das empfangende System sie benötigt.
Ein sichtbares Zeichen kann außerdem aus mehreren Codepunkten bestehen, etwa aus einem Buchstaben mit einem nachfolgenden kombinierenden Akzent. Sichtbare Zeichen, Codepunkte und Bytes können deshalb unterschiedliche Anzahlen ergeben.
Kerngedanke: ASCII deckt einen kleinen Zeichenvorrat ab. Unicode identifiziert Zeichen verschiedener Schriftsysteme. UTF-8 kodiert sie als Bytes, die der Leser nach denselben Regeln dekodieren muss.