Unicode & Co

Ich glaub, ich hab das jetzt zum dritten Mal nachgeguckt. Die ganzen Zeichenkodierungen, Zeichensätze, etc. sind dann doch schon recht kompliziert. Die Wikipedia-Artikel sind da zwar sehr ausführlich, aber letztendlich zu detailliert um sich schnell mal n Überblick zu verschaffen. Damit ich es mir sparen kann in nem halben Jahr ein viertes Mal zu recherchieren, hab ich das jetzt mal kurz zusammen geschrieben in der Hoffnung, dass ich mirs dann besser behalten kann. Ich will das Ganze noch nicht als „Tutorial“ bezeichnen, weil es nicht so ganz meinen Qualitätskriterien entspricht (gut, zugegebenermaßen meine älteren Tutorials auch nicht). Vielelicht bau ich das irgendwann mal aus. Das „schnell“ mal zusammenschreiben hat aber momentan genug Arbeit gemacht und so begnüge ich mich erstmal damit.

Warum ist das eigentlich so kompliziert?

Aus drei Gründen:

  1. Die ganzen Zeichen der verschiedenen Sprachen, die letztendlich kodiert werden sollen, sind schon kompliziert. Das lateinische Alphabet ist da ja noch einfach, wobei es hier auch diverse Diakritische Zeichen gibt. Für einigermaßen typographisch korrekten Schriftsatz gehören dann auch noch diverse Ligaturen dazu. Deutlich schwieriger ist die Sache schon, wenn man beispielsweise Chinesische (sehr viele Zeichen) oder Arabische (hier gibt es unterschiedliche Schreibweisen für die einzelnen Buchstaben und zudem haben Ligaturen eine viel höhere Bedeutung).
  2. Es gibt diverse Zeichensätze, die von unterschiedlichen Firmen und Gremien entwickelt wurden, auf unterschiedlichen Plattformen eingesetzt werden, sich mit der Zeit geändert haben und zueinander nicht immer kompatibel sind.
  3. Zudem gibt es noch weitere sich widersprechende Anforderungen an solche Kodierungen. Beispielsweise sollten sie nicht unnötig Platz verschwenden, leicht austauschbar sein, damit klar kommen, wenn mal ein Byte verloren geht, etc. Es ist also klar, dass es unmöglich ist, eine Kodierung zu finden, die allen Anforderungen entspricht.

Im Folgenden sehen wir uns die wichtigsten Zeichenkodierungen, Zeichensätze und Konzepte an. Dabei beschränken wir uns auf das, was man so bei der täglichen Arbeit braucht. Eine vollständige Abhandlung würde wohl ganze Bücher füllen und so sind kleine Ungenauigkeiten wohl nicht zu vermeiden.

ASCII

Der wichtigste Zeichensatz ist der sogenannte American Standard Code for Information Interchange ASCII. Er ist 7 Bit breit und umfasst daher genau 128 Zeichen, wovon die ersten 32 Steuerzeichen sind, die teilweise gar nicht mehr benutzt werden. Der Rest sind die lateinischen Buchstaben (keine deutschen Umlaute) und die wichtigsten Satzzeichen.

Viele größere Zeichensätze sind kompatibel mit ASCII und so bildest ASCII quasi den kleinsten gemeinsamen Nenner für Zeichensätze.

ISO-8859

Unter der Norm ISO-8859 sind 15 8-Bit-Zeichensätze definiert, die alle zu ASCII und auch bedingt untereinander kompatibel sind. Folgendes ist hier zu beachten:

  1. Es gibt genau genommen einen Unterschied zwischen ISO/IEC 8859 und ISO-8859 (wichtig ist hierbei der Bindestrich). ISO/IEC 8859 definiert die Zeichen 0-32 und 128-159 nicht. Bei ISO-8859 hingegen sind alle Zeichen 0-127 identisch mit dem ASCII-Zeichensatz und 128-159 werden für weitere Steuerzeichen verwendet.
  2. Die Nummer 160 steht für das feste Leerzeichen (engl. non-breaking space) in HTML bekannt als „ “. Das ist ein Leerzeichen, wie jedes andere auch – mit dem Unterschied, dass es hier keinen Zeilenumbruch gibt.
  3. 173 steht – außer bei ISO-8859-11 – für den bedingten Trennstrich (engl. soft hyphen), der normalerweise nur am Zeilenende sichtbar ist. Dieser ist in HTML bekannt als „­“.
  4. ISO-8859-1 („Latin-1“) definiert Zeichen für Westeuropäische und ähnliche Sprachen und ist sehr weit verbreitet. Allerdings gibt es hier kein €-Zeichen.
  5. ISO-8859-15 („Latin-9“) ist eine neuere Variante von ISO-8859-1, wobei hier ein €-Zeichen definiert ist. Jedoch ist dieser Zeichensatz inkompatibel zu ISO-8859-1 und anderen Zeichensätzen, weshalb er sich nicht wirklich durchsetzen konnte.
  6. Praktischerweise sind die deutschen Umlaute, sowie das „ß“ bei den meisten ISO-8859-Zeichensätzen vorhanden und liegen an den gleichen Stellen, weshalb sich deutsche Texte leicht mit osteuropäischen (ISO-8859-2), türkischen (ISO-8859-9), nordischen (ISO-8859-10) und anderen Texten mischen lassen.
  7. Nicht alle Zeichensätze der ISO-8859-Familie haben sich auch durchgesetzt und nicht alle ISO-8859-Zeichensätze halten das, was sie zu versprechen scheinen. z.B. definiert ISO-8859-6 arabische Schriftzeichen und wird auch dafür verwendet, jedoch lässt sich damit arabische Schrift nicht adäquat darstellen.

„Codepages“

Codepages sind nichts anderes, als Zeichensätze. Häufig sind damit aber die proprietären Zeichensätze von IBM und Microsoft gemeint bzw. deren Nummerierung von Zeichensätzen.

„DOS-Codepages“

Die Ur-Codepage ist Codepage 437, die ursprünglich für den IBM-PC entwickelt wurde. Diese enthält neben den ASCII-Zeichen ein paar griechische Buchstaben, lateinische Buchstaben mit Akzenten, mathematische Symbole und vor allem so genannte „box drawing characters“ (Rahmenzeichen) also Zeichen, die dazu verwendet wurden, einfache grafische Oberflächen zu zeichnen. Das besondere an den „DOS-Codepages“ war, dass einige Zeichen doppelte Bedeutungen hatten. Die Nummer 225 wurde beispielsweise sowohl für das griechische kleine Beta (β), alsauch für das deutsche Eszett (ß) verwendet. Auch hatten die Steuerzeichen 1-31 eine Doppelbedeutung. Sie konnten entweder als eben solche verwendet werden oder als Symbolzeichen. So diente das Zeichen Nummer 13 als Zeichen für CarriageReturn (Wagenrücklauf), stellte aber auch eine Achtelnote (♪) dar.

Später wurde Codepage 850 („DOS-latin1“) eingeführt. Hierbei wurde ein Großteil der griechischen Buchstaben sowie ein Teil der Rahmenzeichen durch bislang fehlende Zeichen ersetzt um alle Zeichen aus ISO 8859-1 darstellen zu können. Daneben existieren weitere DOS-Codepages für weitere Sprachen, ähnlich ISO/IEC 8859.

„Windows-Codepages“

Microsoft ist ja bekannt dafür, Standards… ähm… kreativ auszulegen. So auch hier. Statt ISO/IEC 8859 bzw. ISO-8859 definiert Microsoft eigene Codepages, die an ISO-8859 angelehnt sind. Anstatt den Bereich 128-159 leer zu lassen oder mit Steuerzeichen zu füllen, definiert Microsoft hier druckbare Zeichen. Codepage 1252 (auch: „Windows-1252“) basiert so auf ISO-8859-1, Codepage 1250 (auch: „Windows-1250“) auf ISO-8859-2, etc.

Pseudo-Codepages

Zumindest unter Delphi bezeichnet „Codepage 0“ die Default-Codepage, d.h. die Codepage wird zur Laufzeit ermittelt (d.h. der Systemstandard benutzt) und die Codepage mit der Nummer hexadezimal $FFFF (also -1) ist ein Dummy „RawByteString“. Bei RawByteStrings geschieht keine automatische Umkodierung bei Zeichnsatzwechsel.

„ANSI“

Kurz und schmerzlos: Einen ASNI-Zeichensatz gibt es nicht. Das American National Standards Institute (das amerikanische Äquivalent zu unserer DIN) hat mal ein paar Entwürfe gemacht, die irgendwie in ISO-8859 eingeflossen sind. Gemeint ist also meist ISO-8859-1 bzw. Codepage 1252, es kann aber auch irgend ein anderer ISO-8859-Zeichensatz oder ein darauf basierender gemeint sein.

Andere Zeichensätze

Es gibt noch viele weitere Zeichensätze, die teilweise Herstellerspezifisch sind (z.B. EBCDIC für IBM-Großrechner oder MacRoman für Mac), teilweise auch für spezielle Schriftsysteme (z.B KOI8-R für Russischh).

genauer betrachtet…

Genauer betrachtet definiert eine Codepage ja nur ein Mapping zwischen Bytefolgen und Zeichen, jedoch ist damit die Ausgabe ja noch nicht definiert. In der Urzeit der Computer gab es noch keine unterschiedlichen Schriftarten und Internationalisierung war auch noch nicht so das Thema. Das ist mittlerweile natürlich anders und so hat man bei der Entwicklung des Unicode-Standards genauer definiert, was nun ein Zeichensatz, eine Zeichenkodierung, etc. ist. Oftmals werden jedoch diese Begriffe immer noch synonym verwendet. Aus Bequemlichkeit, Gewohnheit, etc. Zum Verständnis ist es dennoch wichtig die Unterschiede zu kennen.

character repertoire
Die Menge der codierbaren Zeichen. „Zeichen“ ist hierbei abstrakt zu sehen. Es geht nicht um die konkrete Darstellung (Glyphen), sondern um die Bedeutung. Beispiel: Das Zeichen „kleines lateinisches a“ kann unterschiedlich dargestellt werden (in unterschiedlichen Fonts). Trotzdem ist es immer der selbe Buchstabe. Umgekehrt kann es vollkommen gleich aussehende Zeichen geben, die aber eine unterschiedliche Bedeutung haben. So sehen das große lateinische A und das große griechische Alpha vollkommen gleich aus, sind aber unterschiedliche Zeichen.
coded character set
Eine Abbildung, die jedem Zeichen aus dem character repertoire einen so genannten Codepoint, also eine eindeutige natürliche Zahl zuordnet. Beispiele: Unicode, ISO-8859-1.
character encoding form/Kodierungsform
Die Kodierung eines Codepoint durch Integer-Einheiten „code units“ von fester Größe (1 Byte, 2 Byte, 4 Byte). Dabei können auch mehrere dieser Einheiten verwendet werden um ein Zeichen zu kodieren. Beispiele: UTF-8, UTF-16, UTF-32, UCS-2.
character encoding scheme/Kodierungsschema
Das character encoding scheme mappt nun die Codeeinheiten in einen Bytestrom. Das kann im einfachsten Falle sehr trivial sein. Bei UTF-8 z.B. sind die Codeunits genau ein Byte groß, wodurch hier meist einfach dieses Byte direkt in den Bytestrom eingeht. Bei größeren Codeunits muss man zumindest noch die Byte-Reihenfolge (byte order, „Endianness“) spezifizieren. Daneben existieren noch weitere character encoding schemes, die beispielsweise den Output komprimieren.

Zeichenkodierung bzw. character encoding ist somit eine Kombination aus character encoding form und character encoding scheme. Die bisher vorgestellten ISO-8859, etc. machen diese genaue Unterscheidung noch nicht. Man kann diese aber problemlos unter coded character set einsortieren. Prinzipiell könnte man also die Codepoints, die ISO-8859 definiert auch anders kodieren.

Die andere Richtung, also das Darstellen der Texte übernimmt die Schriftart (Font, typeface), die den einzelnen Characters Glyphen, also druck- und darstellbare Zeichen zuordnet.

Visualisierung der UFT-16(LE)-Kodierung eines Strings.
Visualisierung der UFT-16(LE)-Kodierung eines Strings.

Unicode

Sehen wir uns nun einmal Unicode etwas genauer an. Unicode ist ein internationaler Standard, der das Ziel hat, alle Zeichen aller Schriftsysteme der Welt zu erfassen. Mittlerweile umfasst Unicode über 100000 Zeichen. Die ersten 128 Zeichen sind dabei identisch mit ASCII und die ersten 65536 Codepoints bilden die so genannte Basic Multilingual Plane (BMP), also den Bereich der wichtigsten Zeichen. Unicode ist in 17 so genannte Ebenen unterteilt, von denen jede 16 Bit, d.h. 65536 Codepoints umfasst. Die BMP ist dabei die erste Ebene „Plane 0“. Die Ebenen wiederum sind dann wieder in zusammengehörige Blöcke unterteilt, die mehr oder weniger einzelnen Schriftsystemen entsprechen.

Unicode: Basic Multilingual Plane
Unicode: Basic Multilingual Plane

Unicode Codepoints

Die Codepoints von Unicode werden normalerweise mit U+nnnn bezeichnet, wobei nnnn die hexadezimale Nummer bezeichnet. „A“ („LATIN CAPITAL LETTER A“) hat somit den Codepoint U+0041.

UTF

Das Unicode Transformation Format ist eine character encoding form für Unicode. Definiert werden u.a. die Varianten UTF-8 (8 Bit breite Codeunits), UTF-16 (16 Bit breite Codeunits) und UTF-32 (32 Bit breite Codeunits). UTF-32 kann alle Unicode-Zeichen in einer Codeunit speichern. UTF-16 und UTF-8 brauchen ggf. mehrere Codeunits, wobei UTF-8 mit ASCII kompatibel ist. Unter Linux ist UTF-8 weit verbreitet.

UCS

Das Universal Character Set ist effektiv nichts anderes als Unicode. Der internationale Standard ISO/IEC 10646 nennt Unicode eben UCS. Interessant ist hierbei ein historischer Unterschied zwischen Unicode und UCS. UCS definierte nämlich ursprünglich andere character encoding forms. Diese nennen sich UCS-2 (16 Bit breite Codeunits) und UCS-4 (32 Bit breite Codeunits). UCS-4 ist identisch mit UTF-32, zwischen UTF-16 und UCS-2 existiert jedoch ein Unterschied. UCS-2 kann nicht alle Unicode-Zeichen darstellen, denn im Gegensatz zu UTF-16 wird ein Zeichen immer durch genau eine Codeunit dargestellt. Mittlerweile definiert ISO/IEC 10646 ebenfalls die UTF-Encodings, jedoch ist insbesondere UCS-2 noch relevant, da es sich immer wieder mal als Altlast wiederfindet.

Combining Characters

Für diakritische Zeichen gibt es einen besonderen Mechanismus in Unicode: die so genannten combining characters. Man kann damit die diaktitischen Zeichen mit anderen kombinieren. Da es auch „precomposed characters“, also schon fertig zusammengesetzte Zeichen gibt, lassen sich manche Zeichen auf verschiedene Art und Weise darstellen. Das Zeichen ‚ḗ‘ z.B. ist ein e mit Makron und Acute und kann als precomposed character (U+1E17), als precomposed e mit Makron (U+0113) kombiniert mit Acute (U+00B4) oder als e (U+0065) kombiniert mit Makron (U+00AF) und Acute (U+00B4) kodiert werden.

BOM

Um für Texte in Textdateien die Kodierung zu spezifizieren kann man der Textdatei die so genannte Byte Order Mark voranstellen. So kann ein Programm, das die Datei ausliest, direkt die Kodierung auslesen und muss diese nicht erraten.

WideChar

Die WideChar/WideString-Datentypen (wchar_t bzw. wchar_t * unter C++) sind compilerspezifisch, können unterschiedlich breit sein und unterschiedliche Kodierungen verwenden. Unter Win32 ist das meist UTF-16 unter Unix meist UTF-32.

Schriftarten

Wir haben nun gesehen, wie man Texte kodieren kann, wie man Texte also als Bytestream auf die Platte bekommt. Für die andere Richtung – also Texte dem User auf dem Bildschirm zu präsentieren – ist eine Schriftart nötig, die jedem Character ein Glyph, also ein darstellbares Zeichen zuordnet. Folgendes sei dazu noch erwähnt:

  • Keine heutige Schriftart kann alle definierte Unicode-Zeichen darstellen.
  • Die typischen Formate für Schriftarten (TrueType, OpenType) haben eine interne Begrenzung auf maximal 65536 Glyphen.
  • Die Unicode-Schriftarten können also nur einen Teil der möglichen Unicode-Zeichen darstellen. Das reicht aber meistens aus.
  • Wingdings und ähnliche Schriftarten definieren Symbole anstelle von Buchstaben. Das heißt in diesem Falle aber, nur, dass die Darstellung eine andere ist, d.h. Buchstaben sehen hier wie Handsymbole, Smileys, etc. aus, sind aber immer noch Buchstaben, wohingegen Unicode solche Symbole getrennt kodiert.

Links

  • Imperia-Unicode-Howto: Der erste Teil ist der interessante. Verständlich geschrieben, allerdings nicht immer 100% korrekt. Bietet trotzdem einen guten Überblick. Der zweite Teil ist ein HowTo zu deren Produkt (ein CMS oder sowas). Kann man aber leicht ignorieren… 😉
  • Mapping of Unicode characters
  • UniSearcher: Eine Unicode-Suchmaschine.
  • UniView: eine weitere Unicode-Suchmaschine
  • Unicode-Tabellen als PDFs
  • Wikipedia-Portal:Unicode
  • Mit dem Gnome-Programm Gucharmap dem Äquivalent der charmap.exe unter Windows kann man auch schön Zeichen suchen. Das KDE-Äquivalent nennt sich kcharmap.
  • Die verlinkten Wikipedia-Artikel enthalten meist schöne Tabellen. Manchmal sind die deutschen, manchmal die englischen Tabellen besser. Es lohnt sich also, beide anzugucken.

a href=

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert