Character-Encoding: Warum “ö” manchmal als “ö” dargestellt wird
Zeichen-Codierungs-Probleme passieren erstaunlich häufig. Besonders in Sprachen, die hauptsächlich lateinische Buchstaben mit wenigen Sonderzeichen verwenden. In diesem Beitrag geht es um diese seltsamen “ö”-Symbole und was hinter den Kulissen eigentlich passiert.
Vor ein paar Wochen erhielt ich die folgende E-Mail:
„Unser Versandpartner meldet sich telefonisch oder per Mail zur Ankündigung der Lieferung. Aufgrund des großen Bestellaufkommens können wir dies aktuell jedoch nicht garantieren.“
Das ist ein sehr häufiges Encoding-Problem, was ständig auftaucht. Aber warum passiert das? Um das Problem zu verstehen, müssen wir zunächst klären, was mit Encoding gemeint ist.
Wie Computer Text darstellen: ASCII
Computer arbeiten grundsätzlich nur mit Zahlen, also muss es eine Möglichkeit geben, eine Zahl als Buchstabe, bzw. als Zeichen, zu interpretieren. Wenn man weiß, wie ein Zeichen repräsentiert wird, kann man beliebigen Text als Folge von Zahlen darstellen, auch “Strings” genannt. Diese Darstellung von Zahlen als Zeichen nennt man Character-Encoding.
Eine der einfachsten Codierungen ist als ASCII bekannt und weist jeder Zahl genau ein Zeichen zu. Obwohl ASCII-Zeichen in einem Byte gespeichert werden, das 256 mögliche Werte darstellen kann, umfasst ASCII nur 128 Zeichen. Ursprünglich wurde ein Bit zur Fehlerüberprüfung reserviert. Später wurde eine erweiterte ASCII-Version (ISO 8859-1) eingeführt, die alle 256 möglichen Zahlen nutzt. Da es nur relativ wenige sind, lassen sich ASCII-Zeichen problemlos in einer Tabelle darstellen:
| Nr. | Zeichen | Nr. | Zeichen | Nr. | Zeichen | Nr. | Zeichen | Nr. | Zeichen | Nr. | Zeichen | Nr. | Zeichen | Nr. | Zeichen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Ctrl-@ | 16 | Ctrl-P | 32 | | 48 | 0 | 64 | @ | 80 | P | 96 | ` | 112 | p |
| 1 | Ctrl-A | 17 | Ctrl-Q | 33 | ! | 49 | 1 | 65 | A | 81 | Q | 97 | a | 113 | q |
| 2 | Ctrl-B | 18 | Ctrl-R | 34 | " | 50 | 2 | 66 | B | 82 | R | 98 | b | 114 | r |
| 3 | Ctrl-C | 19 | Ctrl-S | 35 | # | 51 | 3 | 67 | C | 83 | S | 99 | c | 115 | s |
| 4 | Ctrl-D | 20 | Ctrl-T | 36 | $ | 52 | 4 | 68 | D | 84 | T | 100 | d | 116 | t |
| 5 | Ctrl-E | 21 | Ctrl-U | 37 | % | 53 | 5 | 69 | E | 85 | U | 101 | e | 117 | u |
| 6 | Ctrl-F | 22 | Ctrl-V | 38 | & | 54 | 6 | 70 | F | 86 | V | 102 | f | 118 | v |
| 7 | Ctrl-G | 23 | Ctrl-W | 39 | ' | 55 | 7 | 71 | G | 87 | W | 103 | g | 119 | w |
| 8 | Ctrl-H | 24 | Ctrl-X | 40 | ( | 56 | 8 | 72 | H | 88 | X | 104 | h | 120 | x |
| 9 | Ctrl-I | 25 | Ctrl-Y | 41 | ) | 57 | 9 | 73 | I | 89 | Y | 105 | i | 121 | y |
| 10 | Ctrl-J | 26 | Ctrl-Z | 42 | * | 58 | : | 74 | J | 90 | Z | 106 | j | 122 | z |
| 11 | Ctrl-K | 27 | Ctrl-[ | 43 | + | 59 | ; | 75 | K | 91 | [ | 107 | k | 123 | { |
| 12 | Ctrl-L | 28 | Ctrl-\ | 44 | , | 60 | < | 76 | L | 92 | \ | 108 | l | 124 | ` |
| 13 | Ctrl-M | 29 | Ctrl-] | 45 | - | 61 | = | 77 | M | 93 | ] | 109 | m | 125 | } |
| 14 | Ctrl-N | 30 | Ctrl-^ | 46 | . | 62 | > | 78 | N | 94 | ^ | 110 | n | 126 | ~ |
| 15 | Ctrl-O | 31 | Ctrl-_ | 47 | / | 63 | ? | 79 | O | 95 | _ | 111 | o | 127 | DEL |
Damit funktionierte die Codierung bei einfachem englischen Text gut, allerdings mit einer offensichtlichen Einschränkung. Man kann nur Zeichenfolgen darstellen, die diese 128 Zeichen enthalten. Benötigt man ein Sonderzeichen wie „ö“, bekommt man ein Problem. Es gab zwar zahlreiche lokale Varianten von ASCII, aber kein gemeinsames einheitliches Encoding. Genau hier setzt die nächste Codierung an.
Die UTF-8-Codierung
UTF-8 wurde als abwärtskompatibel mit ASCII entwickelt. Um mehr Zeichen unterzubringen, wird ein neues Konzept eingeführt: variable-width encoding. Beginnt eine Bytefolge mit einem speziellen leading byte, wird das Zeichen als 2-Byte, 3-Byte oder größer interpretiert.
Damit können ausreichend viele Zeichen abgebildet werden, während bei reinem ASCII-Text die Speicherung weiterhin effizient bleibt. Nutzt man eine Sprache mit vielen Sonderzeichen, sinkt die Speichereffizienz, da alle Zeichen den leading byte enthalten.
Um dem entgegenzuwirken, wurde UTF-16 entwickelt, es verwendet 16 Bit bzw. 2 Bytes zur Speicherung eines Zeichens und nutzt zusätzlich die variable Breite für Sonderzeichen, die sich nicht mit 16 Bit darstellen lassen.
Wahl der falschen Codierung
Solange alle dieselbe Codierung verwenden, kann eine Nachricht problemlos versendet und verstanden werden. Probleme entstehen, wenn man in einer anderen Codierung sendet als der Empfänger erwartet.
Beispiel: Jemand sendet mir eine Nachricht in UTF-8, wobei „ö“ als Zwei-Byte-Zeichen dargestellt wird. Ich interpretiere die Bytes jedoch als eine Variante von ASCII. Das Ergebnis: Beide Bytes erscheinen als Zeichen, nämlich „Ó und „¶“.
Dasselbe kann natürlich auch umgekehrt passieren:
Beispiel: Jemand sendet mir eine Nachricht in seiner Variante von erweitertem ASCII (z.B. Windows-1252), wobei „ö“ als Ein-Byte-Zeichen dargestellt wird. Ich interpretiere dieses Byte allerdings als UTF-8. das ursprüngliche Zeichen sieht dann so aus: „�“.
Wie man es verhindern kann
Heutzutage haben sich die meisten Dienste auf UTF-8 geeinigt. Um Missverständnisse bei automatisierten Systemen zu vermeiden, werden fast alle HTTP-Nachrichten mit einem Header versehen, der den Inhalt und die Codierung benennt:
Content-Type: text/html; charset=UTF-8
Darüber hinaus kann HTML selbst ein zusätzliches Meta-Tag enthalten, um die Codierung festzulegen:
<meta charset="UTF-8">
Trotzdem muss man, um herauszufinden, welche Codierung verwendet wird, ironischer Weise erst einen speziellen Header lesen, der selbst natürlich in einer Codierung gespeichert ist.
Fazit
Im Deutschen, mit wenigen Sonderzeichen, stört es oft nicht groß, wenn Codierungsfehler auftreten, weil der Text weiterhin lesbar bleibt. Deswegen kümmert es die meisten auch nicht, wenn sowas mal passiert.
Zurück zur ursprünglichen Nachricht: Ich bin mir ziemlich sicher, dass mein E-Mail-Client UTF-8 verwendet. Stattdessen ist wahrscheinlicher, dass ein Backend-Prozess der automatischen Mail-Verarbeitung zwischendrin von einer falschen Codierung ausgegangen ist, was anschließend zu diesem Fehler geführt hat.
Wenn du im Internet unterwegs bist, stößt du früher oder später auf solche Zeichenfehler. Beim nächsten mal, wenn du über diesen Fehler stolperst, versuch doch einmal anhand der Zeichen herauszufinden, wie die Codierung falsch gelaufen ist.
)
)
)
)
)
)
)
)
)
)