Nachdem Sie die Binärdarstellung von Ganzzahlen kennengelernt haben: Wie würden Sie einen Namen binär codieren? Überlegen Sie dazu: Wie viele Bits werden pro Zeichen benötigt, um die dafür mindestens benötigten Zeichen zu codieren? Wie könnte der Name “BEA BUX” in dieser Codierung aussehen?
Sollen neben Groß- auch Kleinbuchstaben a–z dargestellt werden können, wird ein zusätzliches Bit benötigt, da sich der Zeichenumfang verdoppelt. Mit Ziffern, Satz- und Sonderzeichen wie Währungssymbolen, diakritischen Zeichen (z. B. Umlauten) und anderen Buchstaben des lateinischen Schriftsystems kommen schnell mehrere 100 Zeichen zusammen, für die unterschiedliche Codes benötigt werden. Für eine universelle Zeichencodierung, die auch umfangreichere Symbol- und Schriftsysteme wie das Chinesische oder Japanische umfasst, müssen dagegen mehrere 10 000 bis 100 000 Zeichen codierbar sein. Damit diese Daten eindeutig interpretierbar sind, muss in einem Standard festgelegt werden, durch welche Zahl welches Zeichen repräsentiert wird und wie diese Zahlenwerte binär codiert werden.
In dieser Lektion werden wir uns systematisch mit der Codierung von Textzeichen beschäftigen und die verbreiteten Standards zur Zeichencodierung (z. B. für Textdateien) untersuchen.
Ein Zeichensatz (engl. character set oder kurz charset) beschreibt die Menge der zur Verfügung stehenden Zeichen, die dargestellt werden können, und legt für jedes Zeichen einen Zahlenwert fest. Die darstellbaren Zeichen werden also durchnummeriert. Der feste Zahlenwert eines Zeichens in einem Zeichensatz wird als Codepoint bezeichnet. Codepoints werden in der Regel hexadezimal, aber auch dezimal dargestellt.
Eine Zeichencodierung legt dagegen für jeden Codepoint bestimmte Byte-Werte fest, durch die das Zeichen binär codiert wird. Die früheren Zeichensätze wie ASCII oder ANSI (siehe unten) umfassten nicht mehr als 256 Zeichen, so dass der Unterschied zwischen Codepoint und Zeichencodierung keine Rolle spielte: Hier wurde ein Zeichen einfach durch die Binärdarstellung seines Codepoints codiert. Bei aktuellen Zeichensätzen wie Unicode, die mehrere 100 000 Zeichen umfassen, sind Codepoint und Codierung nicht unbedingt identisch, aber dazu später mehr.
Wie beginnen zunächst mit den einfachen Zeichencodierungen, in denen jedes Zeichen durch 1 Byte codiert wird.
Der Standard ASCII (kurz für American Standard Code for Information Interchange) wurde ursprünglich bereits 1963 entwickelt. Er definiert eine 7-Bit-Zeichencodierung, die als Grundlage der meisten heute gebräuchlichen Zeichencodierungen dient. Der ASCII-Zeichensatz umfasst 27 = 128 Zeichen, die als Byte mit führendem 0-Bit dargestellt werden. Dabei stellen nur die Zeichen 32 bis 126 (hexadezimal 20
bis 7E
) druckbare Symbole dar.
Die folgende Tabelle zeigt alle Zeichen und ihre Hexadezimal-Codes im ASCII-Zeichensatz (spezielle, meist nicht druckbare Zeichen sind kursiv dargestellt):
Code (hex.) | …0 | …1 | …2 | …3 | …4 | …5 | …6 | …7 | …8 | …9 | …A | …B | …C | …D | …E | …F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0… | NUL | SOH | STX | ETX | EOT | ENQ | ACK | BEL | BS | HT | LF | VT | FF | CR | SO | SI |
1… | DLE | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN | EM | SUB | ESC | FS | GS | RS | US |
2… | SP | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
3… | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
4… | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
5… | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
6… | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
7… | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ | DEL |
Das Zeichen SP mit dem Hexadezimal-Code 20
(dezimal 32) stellt dabei das Leerzeichen (engl. space) dar.
Beispiel:
Die Zeichenfolge “Hallo, Kiel!” wird im ASCII-Zeichencode durch die Bytefolge 48 61 6C 6C 6F 2C 20 4B 69 65 6C 21
(hexadezimal) repräsentiert.
Zeichen | H | a | l | l | o | , | K | i | e | l | ! | |
Code (hex.) | 48 | 61 | 6C | 6C | 6F | 2C | 20 | 4B | 69 | 65 | 6C | 21 |
Code (dez.) | 72 | 97 | 108 | 108 | 111 | 44 | 32 | 75 | 105 | 101 | 108 | 33 |
Historisch gesehen baut ASCII auf Zeichencodierungen für Fernschreiber (engl. teletype writer) auf, beispielsweise dem Baudot-Code und insbesondere dem Murray-Code, die wiederum auf Zeichencodierungen für frühere Telegrafen wie dem Morse-Code basieren.
Die ersten 32 Zeichen und das letzte Zeichen im ASCII-Code sind Steuerzeichen für das Ausgabegerät und werden nicht als sichtbare Symbole im Text dargestellt. Diese Steuerzeichen sind historisch durch ihre Verwendung für Fernschreiber begründet, was sich auch an ihren Bezeichnungen erkennen lässt (z. B. “Zeilenvorschub”, “Wagenrücklauf”). Viele dieser Zeichen haben heute in Textdateien keine Bedeutung mehr und können hier ignoriert werden. Für uns sind im Wesentlichen nur die folgenden Steuerzeichen relevant:
Das Tabulator-Zeichen (engl. horizontal tabulator, kurz HT) mit dem Hexadezimal-Code 09
(dez. 9) wird insbesondere in Textdateien verwendet, die Tabellendaten beschreiben, um Daten in einer Zeile voneinander zu trennen. Das Zeichen wird in den meisten Textverarbeitungsprogrammen mit der Tabulator-Taste erzeugt und durch mehrere aufeinanderfolgende Leerzeichen angezeigt.
Ein Zeilenumbruch, der in Textverarbeitungsprogrammen mit der Eingabe-Taste erzeugt wird, wird je nach Betriebssystem unterschiedlich codiert:
0A
(dez. 10) für einen Zeilenumbruch verwendet.0D
(dez. 13), so dass ein Zeilenumbruch hier immer durch zwei aufeinanderfolgende Bytes repräsentiert wird (hex. 0D 0A
).Der ASCII-Zeichensatz wurde ursprünglich nur zur Codierung englischsprachiger Texte entwickelt und enthält daher keinerlei regionale Sonderzeichen wie beispielweise die deutschen Umlaute, das Eszett oder Vokale mit Akzenten – von Buchstaben anderer Alphabete ganz abgesehen.
Aus diesem Grund wurden ab Ende der 1970er verschiedene Standards für Erweiterungen des ASCII-Zeichensatzes veröffentlicht, in denen die übrigen 128 Zeichen, die bei einer 8-Bit-Codierung festgelegt werden können, für verschiedene regionale Schriftsysteme festgelegt wurden. Die bekanntesten dieser Erweiterungen sind zum einen die ISO 8859-Codierungen, zum anderen die Windows Codepages, deren jeweilige Varianten für westeuropäische Sprachen (ISO 8859-1 und Windows-1252) zum Teil auch heute noch (wenn auch im Vergleich zu Unicode in sehr viel geringerem Maße) verwendet werden. Wir betrachten diese beiden Zeichencodierungen hier hauptsächlich deswegen, weil Unicode auf ihnen aufbaut.
Die Normenfamilie ISO 8859 definiert verschiedene 8-Bit-Zeichencodierungen, die den ASCII-Zeichensatz um Sonderzeichen erweitern. Hier werden nur Symbole für die Codepoints 160–255 (hex. A0
–FF
) definiert, die Codepoints 128–159 (hex. 80
–9F
) werden nicht festgelegt. Die Normenfamilie umfasst Standards für verschiedene Schriftsysteme (neben Lateinisch z. B. Arabisch, Griechich, Kyrillisch), die als ISO 8859-1 bis 8859-16 bezeichnet sind.
ISO 8859-1 (auch als Latin-1 bezeichnet) ist dabei die Zeichencodierung für westeuropäische Sprachen und die am weitesten verbreitete Variante der ISO 8859-Normen.1
Die folgende Tabelle stellt die zusätzlichen Zeichen im ISO 8859-1-Zeichensatz dar:
Code (hex.) | …0 | …1 | …2 | …3 | …4 | …5 | …6 | …7 | …8 | …9 | …A | …B | …C | …D | …E | …F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
A… | NBSP | ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | ¬ | SHY | ® | ¯ |
B… | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | º | » | ¼ | ½ | ¾ | ¿ |
C… | À | Á | Â | Ã | Ä | Å | Æ | Ç | È | É | Ê | Ë | Ì | Í | Î | Ï |
D… | Ð | Ñ | Ò | Ó | Ô | Õ | Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß |
E… | à | á | â | ã | ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï |
F… | ð | ñ | ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
Hier werden zwei weitere gebräuchliche Steuerzeichen definiert:
A0
(dezimal 160) stellt das geschützte Leerzeichen (engl. non-breaking space) dar.AD
(dezimal 173) ist das weiche Trennzeichen (engl. soft hyphen). Beispiel:
Die Zeichenfolge “Grüße aus Mölln!” wird in ISO 8859-1 durch die Bytefolge 47 72 FC DF 65 20 61 75 73 20 4D F6 6C 6C 6E 21
(hexadezimal) repräsentiert.
Zeichen | G | r | ü | ß | e | a | u | s | M | ö | l | l | n | ! | ||
Code (hex.) | 47 | 72 | FC | DF | 65 | 20 | 61 | 75 | 73 | 20 | 4D | F6 | 6C | 6C | 6E | 21 |
Code (dez.) | 71 | 114 | 252 | 223 | 101 | 32 | 97 | 117 | 115 | 32 | 77 | 246 | 108 | 108 | 110 |
Die von Microsoft für das Betriebssystem Windows entwickelten Windows Codepages definieren alternative ASCII-Erweiterungen, die zu großen Teilen identisch mit den ISO 8859-Standards sind. Das Äquivalent zu ISO 8859-1 ist Windows-1252 (auch Codepage 1252 oder Western European). Diese Zeichencodierung wird auch oft ANSI-Zeichencode genannt (ANSI steht für American National Standards Institute).2
Windows-1252 unterscheidet sich von ISO 8859-1 nur darin, dass hier auch druckbare Symbole für die meisten der Codepoints 128–159 (hex. 80
–9F
) festlegt werden:
Code (hex.) | …0 | …1 | …2 | …3 | …4 | …5 | …6 | …7 | …8 | …9 | …A | …B | …C | …D | …E | …F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
8… | € | ‚ | ƒ | „ | … | † | ‡ | ˆ | ‰ | Š | ‹ | Œ | Ž | |||
9… | ‘ | ’ | “ | ” | • | – | — | ˜ | ™ | š | › | œ | ž | Ÿ |
Auf diese Weise entstand eine Vielzahl unterschiedlicher Zeichencodierungen für verschiedene Alphabete, in denen dasselbe 8-Bit-Muster je nach Kontext verschiedene Zeichen bedeuten kann. Neben 8-Bit-Zeichencodierungen entstanden dabei auch Codierungen, die mehr Bits pro Zeichen verwenden, um alle relevanten Zeichen zu codieren, etwa für das chinesische oder japanische Schriftsystem.
Der Unicode-Zeichensatz wurde entwickelt, um dem Chaos aus regionalspezifischen Codierungen ein Ende zu bereiten und alle Zeichen in einem Standard zusammenzufassen. Unicode (auch ISO 10646 oder UIC, kurz für Universal Coded Character Set) ist heute der mit Abstand am weitesten verbreitete internationale Standard zur Definition eines global einheitlichen Zeichensatzes.
Ziel des Unicode-Standards ist es, langfristig für jedes Symbol aller weltweit bekannten Schrift- und Zeichensysteme einen Codepoint (“Unicode-Nummer”) festzulegen. Der aktuelle Unicode-Standard (Version 13.0.0, Stand August 2021) umfasst 143 859 Zeichen, darunter neben Schriftzeichen und Währungssymbolen auch geometrische Symbole und Emojis.3
Die ersten 256 Codepoints sind in Unicode identisch mit ASCII und ISO 8859-1 bzw. ANSI (bis auf die Codepoints 128–159, für die in Unicode keine druckbaren Symbole definiert sind, sondern weitere Steuerzeichen).
Da ein Byte hier klarerweise nicht mehr ausreicht, um ein Unicode-Zeichen darzustellen, gibt es verschiedene Standards zur Zeichencodierung, also um die Unicode-Nummern als Byte-Codes darzustellen. Verfahren zur Abbildung von Unicode-Nummern auf Byte-Codes werden als UTF (Unicode Transformation Format) bezeichnet.
Die einfachste, aber auch speicheraufwendigste Methode besteht darin, jedes Unicode-Zeichen mit vier Byte (= 32 Bit) darzustellen, so dass bis zu 232 (also mehr als 4 Mrd.) Zeichen darstellbar sind. Diese Zeichencodierung wird als UTF-32 bezeichnet. Eine UTF-32-codierte Textdatei ist also viermal so groß wie eine mit ANSI oder ISO 8859-1 codierte Datei, auch wenn nur Zeichen aus dem ANSI- bzw. ISO 8859-1-Zeichensatz verwendet werden.
Beispiel:
Die Zeichenfolge “Grüße aus Mölln!” wird in ANSI und ISO 8859-1 durch die Bytefolge 47 72 FC DF 65 20 61 75 73 20 4D F6 6C 6C 6E 21
(hexadezimal) repräsentiert, also durch 16 Byte. Wird UTF-32-Codierung verwendet, werden 64 Byte benötigt, nämlich 00 00 00 47 00 00 00 72 00 00 00 FC 00 00 00 DF
…
Eine bessere Methode besteht darin, variable Codelängen zu verwenden – die Zeichencodierung UTF-8 setzt eine solche Strategie um. UTF-8 ist momentan die mit Abstand am weitesten verbreitete Zeichencodierung für Unicode-Textdateien.4
Hier werden häufiger auftretende Zeichen (geringere Unicode-Nummern) mit weniger Byte codiert als spezielle, seltenere Zeichen (höhere Unicode-Nummern). Das Codierungsverfahren ist folgendermaßen definiert:
Ein Unicode-Zeichen wird in UTF-8 also durch ein bis vier Bytes repräsentiert, wobei gewährleistet ist, dass über 2 Mio. Zeichen darstellbar sind (von denen momentan knapp 7% genutzt werden).
Beispiele:
C4
(hex.) bzw. 196 (dez.), die Binärdarstellung dieser Zahl ist 1100 0100.C3 84
(hex.).1F600
(hex.) bzw. 128 512 (dez.), die Binärdarstellung dieser Zahl ist 1 1111 0110 0000 0000.F0 9F 98 80
(hex.).Für Textdateien sollte in der Regel immer UTF-8 als Zeichencodierung verwendet werden, sofern Sonderzeichen verwendet werden, die über den ASCII-Zeichensatz hinaus gehen, da dieses Format am gebräuchlichsten ist.
In einer Textdatei, die im Textbearbeitungsprogramm (fälschlicherweise) mit der Zeichencodierung ISO 8859-1 angezeigt wird, kommt mehrmals die Zeichenfolge ä vor.
Der folgende Text soll als erweiterter ASCII-Code dargestellt werden (ISO 8859-1 oder Windows-1252/ANSI):
Bei UTF-8 werden
1-4 Byte verwendet,
um ein Zeichen zu
speichern.
Welches Unicode-Zeichen verbirgt sich hinter dem (hier hexadezimal dargestellten) UTF-8-Code F0 9F 91 8D
?
Ermitteln Sie dazu seine Unicode-Nummer aus dem Bitcode und suchen Sie in der Unicode-Zeichentabelle auf https://unicode-table.com/de danach (im Suchfeld oben die Unicode-Nummer als Hexadezimal- oder Dezimalzahl angeben).
Der später eingeführte Standard ISO 8859-15 (auch Latin-9) für westeuropäische Sprachen unterscheidet sich nur in 8 Zeichen von ISO 8859-1 (Latin-1):
Code (hexadezimal) | A4 | A6 | A8 | B4 | B8 | BC | BD | BE |
---|---|---|---|---|---|---|---|---|
Zeichen in ISO 8859-1 | € | Š | š | Ž | ž | Œ | œ | Ÿ |
Zeichen in ISO 8859-15 | ¤ | ¦ | ¨ | ´ | ¸ | ¼ | ½ | ¾ |
Genauer formuliert: Windows-1252 basiert auf einem früheren Entwurf der ANSI-Zeichencodierung, die später mit Änderungen für die Codepoints 128–159 zu ISO 8859-1 wurde. Die Bezeichnung “ANSI” wird heute aber überwiegend synonym für Windows-1252 verwendet. ↩︎
siehe offizielle Website des Unicode-Konsortiums: https://home.unicode.org ↩︎
So verwenden 2021 über 97% aller Webseiten UTF-8 als Zeichencodierung, siehe https://w3techs.com/technologies/cross/character_encoding/ranking ↩︎