Guido Flohr Imperia Unicode- und Multi-Language-HOWTOImperia Unicode- und Multi-Language-HOWTO

Konzeption, Implementierung und Pflege mehrsprachiger Web-Sites mit Imperia

Guido Flohr

Imperia AG
Development

guido@imperia.net

Dieses Dokument ist in folgenden Versionen erhältlich:

Alle Rechte vorbehalten.

25. September 2003

 

Inhaltsverzeichnis

Einleitung
I. Allgemeines
1. Die Zeit vor Unicode
1. Text im Speicher des Computers
2. ASCII
2.1. ASCII-Codeset
2.2. Von Bits und Bytes
2.3. Wieviel Bits werden für ASCII verwendet?
3. 8-Bit-Codesets
3.1. ISO 8859
3.1.1. ISO-8859-1 (Latin-1)
3.1.2. ISO-8859-2 (Latin-2)
3.1.3. ISO-8859-3
3.1.4. ISO-8859-4
3.1.5. ISO-8859-5
3.1.6. ISO-8859-6
3.1.7. ISO-8859-7
3.1.8. ISO-8859-8
3.1.9. ISO-8859-9 (Latin-5)
3.1.10. ISO-8859-10 (Latin-6)
3.1.11. ISO-8859-11
3.1.12. ISO-8859-13 (Latin-7)
3.1.13. ISO-8859-14 (Latin-8)
3.1.14. ISO-8859-15 (Latin-9)
3.1.15. ISO-8859-16 (Latin-10)
3.2. KOI
3.3. Microsoft
3.3.1. CP1252 (Windows-1252)
3.3.2. ISO-8859-15 Revisited
3.3.3. Andere Sprachen, andere Windows-Codepages
3.4. Weitere Hersteller
3.5. Weitere Sprachen
3.5.1. Georgisch
3.5.2. Vietnamesisch
4. Multibyte-Codesets
4.1. CJK-Sprachen
4.1.1. Chinesisch
4.1.2. Japanisch
4.1.3. Koreanisch
4.2. Escaping
4.3. Multi-Byte-Encodings
4.4. Bekannte Multi-Byte-Encodings
5. Zusammenfassung
2. Die schöne Welt von Unicode
1. Was ist Unicode?
2. Der Wertebereich von Unicode
3. Unicode-Properties
4. Technische Repräsentation von Unicode
4.1. Wide Characters
4.1.1. Probleme mit Wide Characters
4.1.1.1. Auf- und Abwärtskompatibilität
4.1.1.2. Speicherverbrauch
4.1.1.3. Synchronisation
4.1.1.4. File-System-Safety
4.1.1.5. Was haben Eier mit Bytes zu tun?
4.1.2. UTF-16
4.1.3. UCS-2
4.1.4. UCS-4
4.2. Multi-Byte-Encodings
4.2.1. UTF-7
4.2.2. UTF-8
4.2.2.1. ASCII-Transparenz
4.2.2.2. Selbstsynchronisierung
4.2.2.3. Speicherverbrauch
4.2.2.4. Nachteile von UTF-8
5. Zusammenfassung
II. Unicode und Multi-Language im Web
3. Web-Standards
1. Hypertext Transfer Protocol HTTP
1.1. Funktionsweise von HTTP
1.2. Der Header Content-Type
1.2.1. Die Konfigurationsanweisung AddDefaultCharset
1.2.2. Die Konfigurationsanweisung AddCharset
1.3. Der Header Content-Language
1.3.1. Die Konfigurationsanweisung DefaultLanguage
1.3.2. Die Konfigurationsanweisung AddLanguage
1.4. Voreingestellte Werte
1.5. Der Header Accept-Charset
1.6. Der Header Accept-Language
1.7. Formulare
2. Extensible Markup Language XML
2.1. Perfomance-Erwägungen
2.2. XML in UTF-8
2.3. Sprachbestimmung
3. Hypertext Markup Language HTML
3.1. Das HTML-Attribut lang
3.2. Das Attribut http-equiv des meta-Elements.
3.3. XHTML
4. Content-Negotiation
4.1. Implementierung mit dem Apache
4.2. Praktische Erwägungen
4.2.1. Sprachpersistenz
4.2.2. Sprachumschaltung
4.2.3. Vertikale oder horizontale Aufteilung
5. Zusammenfassung
III. Unicode und Multi-Language mit Imperia
4. Allgemeines
1. Copy-Pages
2. Unicode-Unterstützung in Imperia
2.1. System- und User-Charset
2.1.1. Wirkung der Sprach- und Charseteinstellungen
2.1.2. Stolpersteine
2.1.3. Templates
2.1.4. Meta-Dateien
2.1.5. Konfiguration des Web-Servers
2.2. Best Practice - eine Empfehlung
2.3. Weitere Unicode-Features
5. Ein Beispielszenario
1. Die Anforderungen
2. Vorbereitung
2.1. System-Einstellungen
2.2. Template und Meta-Datei
2.3. Eine Test-Rubrik
3. Basis-Implementierung
3.1. Mehrsprachige Eingabe
3.1.1. Verallgemeinerung der Spracheingaben
3.1.2. Parametrisierte Code-Includes
4. Dynamische Sprachwahl
4.1. Anpassung der Meta-Datei
4.2. Ein einfaches Workflow-Plug-In
4.2.1. Gerüst für das Plug-In
4.2.2. Workflow-Definition
4.2.3. Implementierung der Plug-In-Logik
4.3. Dynamische Einbindung der Code-Includes
5. Reduzierung der Templates
6. Charset-Konvertierung
7. Verfeinerungen
7.1. Problemfall Flexmodule
7.2. Der Flex-Flexxer
7.3. Mehr Komfort durch DHTML
7.3.1. Erzeugen der Layer
7.3.2. Die DHTML-Erweiterungen am Template
7.3.3. Das Layer-Menü
8. Zusammenfassung
Anhang.
A. Klingonisch (tIhIngan Hol)
Weiterführende Informationen

Tabellenverzeichnis

2.1. Anfangsbyte von UTF-8
2.2. Prinzip von UTF-8

Einleitung

Wer jemals mit Texten zu tun hatte, die weder in englisch noch in einer westeuropäischen Sprache verfasst sind, ist sicherlich schon einmal mit dem Begriff Unicode in Berührung gekommen. Mit Imperia ist es leicht, Content in beliebigen Sprachen zu erfassen und zu pflegen. Allerdings sind dabei einige Besonderheiten zu beachten, die möglichst schon vor Beginn des Projektes Beachtung finden sollten.

Dieses Dokument versucht alle Aspekte der Unicode-Unterstützung in Imperia zu behandeln. Dafür ist natürlich ein gewisses Grundverständnis dafür erforderlich, was sich hinter dem Begriff Unicode überhaupt verbirgt, und in welchem Zusammenhang Unicode mit der Publizierung von Content steht. Bei der Vermittlung dieser Hintergrundinformationen wurde mehr Wert auf Verständlichkeit denn auf hundertprozentige technische Exaktheit gelegt, um auch weniger technisch versierten Anwendern den Einstieg in die Thematik zu erleichtern.

Die Pflege mehrsprachiger Websites hat nicht notwendigerweise etwas mit Unicode zu tun. Das Thema ist jedoch eng genug verwandt, um eine Behandlung innerhalb desselben Dokumentes zu rechtfertigen.

Allgemeines

Inhaltsverzeichnis

1. Die Zeit vor Unicode
1. Text im Speicher des Computers
2. ASCII
2.1. ASCII-Codeset
2.2. Von Bits und Bytes
2.3. Wieviel Bits werden für ASCII verwendet?
3. 8-Bit-Codesets
3.1. ISO 8859
3.1.1. ISO-8859-1 (Latin-1)
3.1.2. ISO-8859-2 (Latin-2)
3.1.3. ISO-8859-3
3.1.4. ISO-8859-4
3.1.5. ISO-8859-5
3.1.6. ISO-8859-6
3.1.7. ISO-8859-7
3.1.8. ISO-8859-8
3.1.9. ISO-8859-9 (Latin-5)
3.1.10. ISO-8859-10 (Latin-6)
3.1.11. ISO-8859-11
3.1.12. ISO-8859-13 (Latin-7)
3.1.13. ISO-8859-14 (Latin-8)
3.1.14. ISO-8859-15 (Latin-9)
3.1.15. ISO-8859-16 (Latin-10)
3.2. KOI
3.3. Microsoft
3.3.1. CP1252 (Windows-1252)
3.3.2. ISO-8859-15 Revisited
3.3.3. Andere Sprachen, andere Windows-Codepages
3.4. Weitere Hersteller
3.5. Weitere Sprachen
3.5.1. Georgisch
3.5.2. Vietnamesisch
4. Multibyte-Codesets
4.1. CJK-Sprachen
4.1.1. Chinesisch
4.1.2. Japanisch
4.1.3. Koreanisch
4.2. Escaping
4.3. Multi-Byte-Encodings
4.4. Bekannte Multi-Byte-Encodings
5. Zusammenfassung
2. Die schöne Welt von Unicode
1. Was ist Unicode?
2. Der Wertebereich von Unicode
3. Unicode-Properties
4. Technische Repräsentation von Unicode
4.1. Wide Characters
4.1.1. Probleme mit Wide Characters
4.1.1.1. Auf- und Abwärtskompatibilität
4.1.1.2. Speicherverbrauch
4.1.1.3. Synchronisation
4.1.1.4. File-System-Safety
4.1.1.5. Was haben Eier mit Bytes zu tun?
4.1.2. UTF-16
4.1.3. UCS-2
4.1.4. UCS-4
4.2. Multi-Byte-Encodings
4.2.1. UTF-7
4.2.2. UTF-8
4.2.2.1. ASCII-Transparenz
4.2.2.2. Selbstsynchronisierung
4.2.2.3. Speicherverbrauch
4.2.2.4. Nachteile von UTF-8
5. Zusammenfassung

Kapitel 1. Die Zeit vor Unicode

Der folgende Schnelldurchlauf soll kurz die Entwicklung von den auf frühen Computersystemen verwendeten Codesets zu Unicode beleuchten. Der Fokus liegt dabei eindeutig auf der Relevanz für Web-Authoring. Für detaillierte Informationen sei auf die ausgezeichneten Darstellungen auf [czyborra.com] von Rainer Czyborra und [Standards] von Dik T. Winter verwiesen.

1. Text im Speicher des Computers

Computer werden auch Rechner genannt, weil ihre Stärke im Rechnen, also im Umgang mit Zahlen liegt. Mit Sprache, ganz gleich ob gesprochen oder geschrieben, haben sie ihre Schwierigkeiten, und so ist es nicht verwunderlich, dass Computer Texte einfach als Zahlenfolge behandeln. Jeder Buchstabe eines Textes ist im Speicher des Computers als eine Zahl abgelegt.

Was passiert aber, wenn ein Text am Bildschirm dargestellt werden soll? Dafür muss der Computer zu jeder Zahl, zu jedem Zeichencode eine passende Grafik haben, damit er, wenn er im Speicher auf beispielsweise die Zahl 65 trifft, etwas am Bildschirm darstellen kann, das wie ein großes A aussieht. Solange man die Texte nur auf dem eigenen Rechner bearbeitet, ist die Zuordnung der nummerischen Codes zu ihrer graphischen Repräsentation (die auch als Glyph bezeichnet wird), willkürlich, sie sollte sich nur nicht ändern. Will man dagegen eine Textdatei auf einem anderen Rechner, mit womöglich einem anderen Betriebssystem, ebenfalls bearbeiten, tut eine Konvention Not, welcher Zahl denn welches Zeichen entsprechen soll.

2. ASCII

In den Urzeiten des Computers war Interoperabilität kein großes Thema, und so grenzt es fast an ein Wunder, dass sich tatsächlich eine Minimalkonvention für die Zuordnung von Codes zu Zeichen durchsetzen konnte, nämlich ASCII, der American Standard Code for Information Interchange. Durchsetzen heißt allerdings nicht, dass es der einzig verwendete Code ist. Es gibt tatsächlich Ausnahmen wie beispielsweise der auf Großrechnern und Mainframes verbreitete EBCDIC.

Die erste Version von ASCII stammt aus dem Jahre 1963. Sie hat bis zur heute gültigen Version aus dem Jahre 1967 einige Änderungen erfahren, die detailliert unter http://www.cwi.nl/~dik/english/codes/stand.html auf [Standards] beschrieben sind.

2.1. ASCII-Codeset

Wie sieht die Zuordnung in ASCII, jetzt genau aus? Die Codes 0-31 sind sogenannte Steuer- bzw. Controlcodes, die für nicht-druckbare Zeichen verwendet werden, beispielsweise Zeilenumbruch oder Tabulator. Das Leerzeichen hat die Nummer 32, die Ziffern 0-9 haben die Codes 30-39, die Großbuchstaben A-Z die Codes 65-90, und die Kleinbuchstaben a-z sind mit 97-122 codiert. Die Zwischenbereiche werden für Interpunktionszeichen und Computerspezifisches wie den Klammeraffen „@“ verwendet.

2.2. Von Bits und Bytes

Was genau ist denn eigentlich ein Byte? Nun, Computer können eigentlich noch nicht einmal (Dezimal-)Zahlen speichern. Vielmehr besteht der Speicher des Computers aus Milliarden oder sogar Billionen winziger Schalter, die entweder ein- oder ausgeschaltet sind. Mit einem solchen System lassen sich daher keine normalen, also Dezimalzahlen, sondern nur Binärzahlen, Zahlen, die lediglich mit Nullen und Einsen dargestellt werden, repräsentieren. Diese einzelnen Kippschalter heißen Bits, und damit die Rechnerei nicht ganz so wüst wird, werden 8 Bits normalerweise zu einem Byte zusammengefasst. Steht an einer Speicherzelle im Computer also die Zahl 65, sieht das in Wirklichkeit so aus:

01000001

Die Zahl 65 in Binärdarstellung

Irgendwo im Speicher unseres Computers liegen 8 Birnchen, einige an, einige aus, und die Kombination von An und Aus steht für die Zahl 65. Aber es sind nur 8 Birnchen, und uns beschleicht der Verdacht, dass man mit diesen 8 Birnchen nicht allzuviele verschiedene Zahlen darstellen kann. Wieviele Kombinationen sind denn wirklich mit diesen acht Birnchen möglich? Mathematik leider nur ausreichend minus, also raten wir: Acht! Nein, Moment, kann nicht sein, die Kombination oben steht ja schon für 65. Also schauen wir im Lexikon nach. Aha, es sind 28 = 256. Hab' ich doch gleich gesagt.

Wir müssen aber auch noch die Zahl Null darstellen können. Also kommen wir mit unseren 8 Birnchen/Bits pro Byte nur von 0-255, weil wir die 256 noch der Null opfern. Weit ist das ja nicht. Wenn man allerdings zwei Bytes (16 Bit) nebeneinander betrachtet, sieht die Sache schon anders aus, denn jetzt haben wir für jede der 256 Kombinationen beim rechten Byte noch 256 Kombinationen beim linken Byte, insgesamt also 256 x 256 = 2562 = 65536. Bei vier Bytes (32 Bit) auf einmal sind es schon 4.294.967.296, bei den heute schon gebräuchlichen acht Bytes (64 Bit) sogar 18.446.744.073.709.551.616. Es kommt Hoffnung auf.

2.3. Wieviel Bits werden für ASCII verwendet?

Speichern wir eine Text-Datei als blanken Text ab (also nicht mit einem Textverarbeitungsprogramm, sondern z. B. mit dem Notepad unter Windows oder vi unter Unix) stellen wir an der Dateigröße fest, dass pro Zeichen (Leerzeichen nicht vergessen!) ungefähr ein Byte an Speicherplatz verbraucht wird. Wenn wir beim Zählen auch Zeilenumbrüche und Tabulatoren nicht vergessen, stellen wir fest, dass es sogar genau ein Byte ist (unter DOS/Windows wird ein Zeilenumbruch allerdings aus Gründen, die das Geheimnis des Erfinders bleiben werden, als zwei Bytes abgespeichert, pro Zeile muss daher noch ein überflüssiges Byte dazugerechnet werden).

Also könn(t)en in einer Textdatei nur 256 verschiedene Zeichen verwendet werden. Ist das wirklich so? Nein, bei ASCII ist es tatsächlich nur die Hälfte, und davon gehen noch einmal die 32 Steuerzeichen (und genaugenommen auch noch die Nummer 127, das Zeichen für die Taste Entf bzw. Del) ab. Bei ASCII werden nämlich nur 7 von 8 möglichen Bits verwendet, hauptsächlich wohl, weil zur Zeit der Definintion von ASCII die meisten Computer-Anwendungen das achte Bit für interne Zwecke verwendeten. Das gilt mit Einschränkungen sogar noch heute. SMTP (Simple Mail Transfer Protocol, siehe [RFC821], inzwischen ersetzt durch [RFC2821] oder auch [RFC822], inzwischen ersetzt durch [RFC2822]), das Netzwerkprotokoll, mit dem E-Mail verschickt wird, kann erst mit einer Erweiterung 8-Bit-Zeichen übertragen. Weil aber noch genügend Mail-Server ohne diese Erweiterung existieren, ist es noch heute üblich, 8-Bit-Mails vor der Übertragung in eine 7-Bit-Darstellung zu konvertieren.

Mit ASCII lassen sich also tatsächlich weniger als 100 Zeichen darstellen. Wir schauen noch einmal im Abschnitt 2.1, „ASCII-Codeset“ nach, welche Zeichen das etwa sind. Wie sieht es beispielsweise mit deutschen Umlauten, französischen akzentuierten Buchstaben, skandinavischen Zeichen aus? Oder griechischen, hebräischen, arabischen, kyrillischen, chinesischen Zeichen. Die sind allesamt nicht definiert, wohlgemerkt, auch die deutschen Umlaute nicht! Wer einen deutschen Text mit Umlauten also als ASCII-Text bezeichnet, weiß nicht, was ASCII ist.

3. 8-Bit-Codesets

Die meisten Computer-Anwendungen kommen schon seit geraumer Zeit blendend mit 8-Bit-Textdaten zurecht, und die Beschränkung auf 7 Bit scheint daher nicht mehr so ganz zeitgemäß. Allerdings müssen wir uns daran erinnern, dass es für die Interoperabilität entscheidend ist, dass eine eindeutige Konvention für die Zuordnung von nummerischen Codes zu entsprechenden Zeichen gegeben ist. Für die Zeichen 0-127 ist das durch ASCII weitestgehend gewährleistet, von 128-255 existiert keine solche Konvention.

Eine Zeitlang herrschte in diesem Bereich sogar völliges Chaos. Jeder Hersteller benutzte seine eigene Konvention für den 8-Bit-Bereich, meistens sogar mehrere, abhängig davon, für welches Land das jeweilige System hergestellt wurde. IBM beispielsweise belegte den Bereich mit einfachen Grafikzeichen (die sogenenannte PC ruler), um mit Winkeln, Strichen und Kreuzen einfache Tabellen, später sogar einfache Fenstersysteme darstellen zu können, in kleinen Teilbereichen waren länderspezifische Zeichen wie deutsche Umlaute, akzentuierte Buchstaben, skandinavische Zeichen etc. darzustellen. Der Atari war teilweise kompatibel zum IBM-PC, statt der Grafikzeichen wurden jedoch hebräische und griechische Zeichen verwendet, der Macintosh hatte ebenfalls seine eigene Zuordnung, auf HP-Systemen ist noch heute ein Codeset namens HP-Roman8 Standard, ...

Wer früher Texte zwischen Computersystemen austauschte, die nicht in Englisch verfasst waren, war daher daran gewöhnt, dass Texte entweder völlig verhunzt ankamen, oder in einer 7-Bit-Ersatzdarstellung verfasst wurden (z. B. „ae“ statt „ä“, „'e“ statt „é“, „c,“ statt „ç“ und so weiter). Verhunzt heißt nicht, dass die Daten tatsächlich beim Transport beschädigt wurden, lediglich die Zuordnung von Codes zu Zeichen stimmte nicht. Tippte ein Unix-Nutzer beispielsweise ein großes „Ä“ ein, wurde dies als Code Nummer 196 gespeichert, was ein Apple-Macintosh als großes F mit Haken („ƒ“) interpretierte.

3.1. ISO 8859

Die International Standardization Organization ISO versuchte mit der Norm ISO 8859 eine gewisse Ordnung in das Chaos zu bringen. In der Norm sind heute 14 Standard-Codesets definiert.

Alle Codesets der Norm ISO 8559 weisen mehr oder weniger große Überschneidungen auf. Im Bereich 128-159 liegen zusätzliche (nicht druckbare) Steuerzeichen, das Zeichen mit der Nummer 160 ist stets das no-break space, das wir in HTML als   kennen, Nummer 173 ist ein Soft Hyphen - ­ (Ausnahme, das noch nicht offiziell standardisierte, auf TIS-620 basierende ISO-8859-11). Auch andere Latin-1-Sonderzeichen, die in ASCII nicht enthalten sind, wie §, ©, ° liegen oft (aber nicht immer) an der gleichen Stelle.

Nicht alle Codesets sind in der Praxis wirklich relevant. Einige haben sich nur teilweise, einige gar nicht durchgesetzt.

3.1.1. ISO-8859-1 (Latin-1)

Geeignet hauptsächlich für westeuropäische und ähnliche Sprachen, zum Beispiel Afrikaans, Bretonisch, Katalanisch, Walisisch, Dänisch, Deutsch, Englisch, Spanisch, Estnisch, Baskisch, Finnisch, Färöisch (Färingisch), Französisch/Wallonisch, Irisch (Gälisch), Galizisch, Manx, Indonesisch (Bahasa Indonesia) , Isländisch, Italienisch, Eskimoisch (Westgrönländisch/Kalaallisut), Malaysisch, Niederländisch/Flämisch, Norwegisch (Bokmål) und Neunorwegisch (Nynorsk), Okzitanisch (->Frankreich), Portugiesisch, Albanisch, Schwedisch, Tagalog (->Philippinen), Usbekisch und viele mehr.

ISO-8859-1 ist heute ein De-Fakto-Standard für 8-Bit-Textdaten, und wird praktisch von allen Computersystemen unterstützt. Prominente Ausnahme im Unix-Bereich ist Hewlett-Packards HP-UX, das ein eigenes Codeset für westeuropäische Sprachen verwendet, Roman8 oder auch HP-Roman8. Bei den Micros relevant sind noch das MS-DOS-Codeset, das noch immer von DOS-Anwendungen unter MS-Windows verwendet wird (Beweis: DOS-Box öffnen und type umlaute.txt eingeben, wenn umlaute.txt eine Textdatei mit deutschen Umlauten ist). Inwieweit die Macintosh-Codesets auf dem Apple noch aktuell sind, ist nicht bekannt.

3.1.2. ISO-8859-2 (Latin-2)

Geeignet für mittel- und osteuropäische Sprachen mit lateinischen Alphabeten, insbesondere Bosnisch, Tscheschisch, Kroatisch, Ungarisch, Polnisch, Rumänisch, Slowakisch, Slowenisch, Serbisch (mit lateinischen Schriftzeichen), etc.

Auch ISO-8859-2 ist im osteuropäischen Raum (soweit keine kyrillischen Zeichen benutzt werden) weitgehend durchgesetzt. Für deutsche Anwender weist ISO-8859-2 die interessante Eigenschaft auf, dass die deutschen Umlaute und das Eszet nicht nur in ISO-8859-2 vorhanden sind, sondern auch an den gleichen Stellen liegen (also die gleichen nummerischen Codes haben). In der Praxis heißt das, dass man deutsche Texte auch in ISO-8859-2 darstellen kann, und somit in ein und derselben Datei deutsche und z. B. polnische Textpassagen haben kann.

3.1.3. ISO-8859-3

Dieses Codeset ist laut Standard für „südosteuropäische und sonstige Sprachen“ vorgesehen. Mir persönlich ist hier nur Maltesisch bekannt.

3.1.4. ISO-8859-4

Geeignet für skandinavische und baltische Sprachen.

3.1.5. ISO-8859-5

Prinzipiell ist dieses Codest für Bulgarisch, Mazedonisch, Russisch, Serbisch (mit kyrillischen Schriftzeichen), Tadschikisch, Ukrainisch, Weißrussisch, etc. geeignet.

Im osteuropäischen Sprachraum, der kyrillische Schriftzeichen verwendet, steht ISO-8859-2 auf der Bedeutungsskala jedoch nur an dritter Stelle. Den ersten Platz in der Gunst der Anwender dürften sich die KOI8-Codesets und die Codesets der Firma Microsoft teilen (wobei die KOI8-Codesets etwas verbreiteter sein sollten). Beiden Familien von Codesets ist ein eigener Abschnitt gewidmet.

3.1.6. ISO-8859-6

Das Codeset ISO-8859-6 ist für Arabisch stark verbreitet, was allerdings nicht zu der Illusion verleiten sollte, dass sich damit arabischer Text adäquat darstellen ließe. Das arabische Alphabet kennt 28 Buchstaben mit jeweils vier, meist unterschiedlichen Schreibweisen. Hierfür braucht man schon 112 unterschiedliche Codes (die ISO-Codesets haben nur 96 Stellen frei, weil die ersten 32 für Steuerzeichen verwendet werden). Hinzu kommen noch die zehn Ziffern, denn die wirklichen arabischen Ziffern unterscheiden sich in der Darstellung erheblich von unseren „arabischen“ Ziffern:

Die arabischen Ziffern 0-9

Die arabischen Ziffern 0-9

Die Ziffern sind natürlich von rechts nach links zu lesen (die Null ist also der Punkt, und die Neun ist das Zeichen, das unserer Neun sehr ähnlich sieht) und sind durch (arabische) Kommata getrennt. Die Satzzeichen wie Punkt, Komma, Semikolon weichen ebenfalls mehr oder weniger stark von der uns geläufigen Darstellung ab.

Hinzu kommt eine Unzahl von Ligaturen, Buchstabengruppen also, die über- und untereinander und ineinander verwoben dargestellt werden. Diese Ligaturen werden keineswegs nur in kalligraphischen Schriften, sondern durchaus auch im Alltagsgebrauch verwendet. Prominentestes Beispiel ist die Darstellung für Gott „Allah“ als Ligatur („Allah“), die praktisch durchweg in dieser Form geschrieben wird. Die arabische Sprache und Schrift hat für gläubige Muslime eine spirituelle Bedeutung, und somit sind solche Eigenheiten besonders ernst zu nehmen. ISO-8859-6 wird diesen Anforderungen nur begrenzt gerecht.

3.1.7. ISO-8859-7

Dieses Codeset ist Standard für Griechisch.

3.1.8. ISO-8859-8

Dieses Codeset enthält den hebräischen Zeichenvorrat.

3.1.9. ISO-8859-9 (Latin-5)

Latin-5 ist eine Variante von Latin-1 für Türkisch.

3.1.10. ISO-8859-10 (Latin-6)

Geeignet für Lappisch, sowie weitere nordische und Eskimo-Sprachen.

3.1.11. ISO-8859-11

ISO-8859-11 ist zur Zeit noch kein offizieller Standard. Es ist praktisch identisch mit dem Codeset TIS-620 für Thailändisch, enthält aber zusätzlich noch das No-Break-Space (aber kein Soft Hyphen).

3.1.12. ISO-8859-13 (Latin-7)

Mit ISO-8859-13 lassen sich interessanterweise nicht nur die baltischen Sprachen Lettisch und Litauisch, sondern auch Maori darstellen, eine Tatsache die allerdings mehr zum Schmunzeln denn zu sprachwissenschaftlichen Spekulationen anregen sollte.

3.1.13. ISO-8859-14 (Latin-8)

ISO-8859-14 enthält akzentuierte Zeichen für keltische Sprachen.

Hinweis: Irisch (Gaeilge) wird gewöhnlich in ISO-8859-1 bzw. ISO-8859-15 codiert. Die aus dem Mittelalter stammende traditionelle irische Schrift wird auch in Irland selbst mehr und mehr durch eine vom lateinischen Alphabet abgeleitete Schrift verdrängt (s. [Ó Siadhail], S. 9).

3.1.14. ISO-8859-15 (Latin-9)

ISO-8859-15 ist der designierte Nachfolger von ISO-8859-1 (s. Abschnitt 3.1.1, „ISO-8859-1 (Latin-1)“). Es ersetzt einige wenig benutzte Zeichen durch die in Latin-1 „vergessenen“ Zeichen für Französisch und Finnisch, nämlich die O-E-Ligaturen (Œ und œ), das große Y mit Trema (Ÿ), und die Konsonanten S und Z mit Caret (Š, š, Ž und ž). Die praktisch bedeutsamste Änderung ist die Ersetzung des allgemeinen Währungssymbols ¤ (das ohnehin kaum jemand zu deuten weiß) durch das Euro-Symbol €.

3.1.15. ISO-8859-16 (Latin-10)

Dieser Standard ist für „sonstige osteuropäische Sprachen“ vorgesehen. Einziges bekanntes Beispiel ist Rumänisch.

3.2. KOI

Parallel zur Standardisierung im Westen, insbesondere mit ASCII, gab es ähnliche Bemühungen in Osteuropa, insbesondere in der ehemaligen Sowjetunion. Ungefähr zur gleichen Zeit wie die ersten Versionen von ASCII enstanden auch die ersten sowjetischen Codeset-Standards des GOST, des sowjetischen Normungsinstituts. GOST 10859 definierte die 10 Ziffern, 22 Interpunktions- und Sonderzeichen, gefolgt vom russischen Alphabet (nur Großbuchstaben), wiederum gefolgt von den 14 lateinischen Buchstaben ohne (graphische) kyrillische Entsprechung, wiederum gefolgt von weiteren Sonderzeichen und dem Härtezeichen Twjordyj Znak.

Mit GOST 13052 folgte ein volles 7-Bit Codeset, in der unteren Hälfte entsprach es exakt dem ASCII-Codeset (das Dollarzeichen $ war natürlich durch das allgemeine Währungssymbol ¤ ersetzt), in der oberen Hälfte waren für die lateinischen Buchstaben jeweils die kyrillischen Zeichen angeordnet, die lautlich dem lateinischen Pendant am nächsten kamen, wobei allerdings Groß- und Kleinbuchstaben vertauscht waren. Wir erinnern uns kurz zurück an die Zeiten, als die ewigen Weltmeister aus der UdSSR noch die Aufschrift CCCP[1] auf ihren Eishockey-Leibchen trugen. Und kein Reporter verpasste während der Endspielübertragung die Gelegenheit, darauf hinzuweisen, dass diese Buchstabenfolge tatsächlich „SSSR“ bedeutete. Und der hungrige Moskau-Tourist lernte spätestens am zweiten Tag, dass sich in den Häusern mit dem Schild PECTOPAH ein „RESTORAN“ verbarg.

Dieser Kniff hatte im Alltag enorme Vorteile. Schickte ein Hacker aus Moskau seinem ins Silicon Valley geflüchteten Vetter den letzten Absatz aus Tolstois Anna Karenina, so sah das an seinem GOST-13052-Terminal zuhause so aus:

Die letzten Zeilen aus Anna
		Karenina

Die letzten Zeilen aus Anna Karenina (Tolstoi)

Am ASCII-Terminal am anderen Ende der Welt, präsentierte sich dieser Text dann wiederum so:

tAK VE BUDU SERDITXSQ NA iWANA-KU^ERA, TAK VE BUDU SPORITX, BUDU NEKSTATI WYSKAZYWATX SWOI MYSLI, TAK VE BUDET STENA MEVDU SWQTAQ SWQTYH MOEJ DU[I I DRUGIMI, DAVE VENOJ MOEJ, TAK VE BUDU OBWINQTX EE ZA SWOJ STRAH I RASKAIWATXSQ W \TOM, TAK VE BUDU NE PONIMATX RAZUMOM, ZA^EM Q MOLOSX, I BUDU MOLITXSQ, - NO VIZNX MOQ TEPERX, WSQ MOQ VIZNX, NEZAWISIMO OT WSEGO, ^TO MOVET SLU^ITXSQ SO MNOJ, KAVDAQ MINUTA EE - NE TOLXKO NE BESSMYSLENIA, KAKO@ BYLA PREVDE, NO IMEET NESOMNENNYJ SMYSL DOBRA, KOTORYJ Q WLASTEN WLOVITX W NEE!

Er sah eine krude, nach kurzer Übungszeit aber durchaus lesbare Transliteration des russischen Originals. Durch die Vertauschung von Groß- und Kleinbuchstaben war auch sofort erkennbar, welche Text-Teile in der jeweils anderen Sprache geschrieben waren. Antwortete der Vetter mit den neuesten sozialpsychologischen Erkenntnissen aus dem Land der unbegrenzten Möglichkeiten, kamen auch diese Weisheiten wieder lesbar am GOST-Terminal in Moskau an:

Dave Barry, „Sex and the Single Amoeba: What Every
		Teen Should Know“

Left as an exercise to the reader...

Dieses Konzept hatte sich bewährt, und wurde auch im später auf 8 Bit (also 256 Zeichen) erweiterten Standard KOI8-R ([RFC1489]) beibehalten. Die untere Hälfte entsprach jetzt exakt ASCII, in der oberen Hälfte wurden parallel zu den lateinischen Buchstaben die phonetischen Pendants der kyrillischen Schrift gelegt. Der Trick hatte weiter seine Daseinsberechtigung: Viele Mail-Applikationen waren noch immer nicht in der Lage 8-Bit zu übertragen, und setzten das achte Bit einfach auf Null zurück. Technisch gesehen hieß das, dass alle 8-Bit-Zeichen um 128 Plätze nach vorne geschoben wurden. Konnte ein kyrillischer Text also nicht korrekt übertragen werden, wurde er also tatsächlich mit lateinischen Buchstaben transliteriert, und kam noch immer lesbar am Bestimmungsort an.

Leider wurde dieser intelligente Trick von KOI8-R nicht in ISO-8859-5, dem offiziellen Codeset für kyrillische Schrift, übernommen, was dazu führte, dass KOI8-R im russischen Sprachraum noch immer wesentlich verbreiteter ist, als ISO-8859-5. Es gibt auch noch weitere Varianten des KOI-Codesets, insbesondere KOI8-U für Ukrainisch und KOI8-T für Tadschikisch.

3.3. Microsoft

Die Firma Microsoft zeichnet sich traditionell durch eine originelle Auslegung von Normen aus. Die Interpretation von Codesets macht hier keine Ausnahme. Innerhalb der graphischen Oberfläche Windows™ ihres Betriebssystems MS-DOS™ schwenkte sie für den europäischen und amerikanischen Markt scheinbar von den in MS-DOS™ verwendeten IBM-Codesets auf das in der Unix-Welt etablierte ISO-8859-1 um.

Allerdings enthält ISO-8859-1, wie alle Codesets der Familie ISO 8859, eine Lücke, die von Microsoft ausgenutzt wurde. Die Zeichen 128-159 werden in ISO 8859 nicht verwendet. Hintergrund: Geht während der Datenübertragung das achte Bit verloren (in Wirklichkeit gibt es Applikationen, die das absichtlich machen, insbesondere Mail-Server und Mail-Reader), werden die 8-Bit-Zeichen faktisch um 128 Plätze nach vorne geschoben. Aus den Zeichen 128-159 würden dann die Steuerzeichen 0-31, was evtl. zu Problemen führen kann: Wird beispielsweise das 8-Bit-Zeichen mit der Nummer 138 nicht komplett übertragen, käme es beim Empfänger als Zeilenumbruch an, was die Lesbarkeit eines Textes nicht fördert. In pathologischen Fällen könnten auch die Vorder- und Hintergrundfarbe verstellt werden, Fenster auf dem Bildschirm verschoben werden, Pieptöne aus dem Lautsprecher kommen, und so weiter.

Auf Windows-Systemen war dieses Problem wenig relevant, auf Unix-Systemen eigentlich auch, die Problemzone wurde von ISO dennoch freigehalten. Um der Wahrheit die Ehre zu geben: Man muss schon ein ziemlich lausiger Programmierer sein, um eine Anwendung, die Texte verarbeitet, durch solche Control-Codes (also die Zeichen mit der Nummer 0-31) aus der Fassung zu bringen, denn immerhin könnte ein böswilliger Anwender diese bösartigen Steuerzeichen ja auch absichtlich z. B. als Mail verschicken. Die ISO nahm dennoch Rücksicht auf diese fehlerhaften Programme, und einige selbsternannte Gralshüter in der Unix-Welt verteidigen diese Einschränkung noch immer vehement, und verweisen bei den praktischen Erwägungen (es fehlten schlicht und ergreifend wichtige Zeichen in ISO-8859-1) auf das Allheilmittel Unicode. Sie übersehen dabei meist, dass praktisch alle Unicode-Anwendungen (sofern sie UTF-8 verwenden) hemmungslos, sogar in viel höherem Maße, genau diese Problemzone für textuelle Daten verwenden.

3.3.1. CP1252 (Windows-1252)

Was hat Microsoft jetzt genau gemacht? Microsoft benutzt ein gegenüber ISO-8859-1 leicht modifiziertes Codeset namens CP1252 (CP wie CodePage) zur Darstellung westeuropäischer Texte:

CP1252 (Windows-1252)

CP1252 (Windows-1252)

Erläuterung: Die Kästchen in den ersten beiden Reihen (0-31 oder hexadezimal 00-1F) sind die eigentlichen Control-Chars, die zum größten Teil nicht darstellbar sind. Die Control-Chars, die zur Formatierung von Text verwendet werden (Zeilenumbruch, Tabulatoren, Seitenvorschub, ...) sind einfach leer. Die „Problemzone“ erstreckt sich von der 9.-10. Zeile (128-159 bzw. hexadezimal 80-9F). Wie man sieht, wurde sie durchaus sinnvoll gefüllt: Das Euro-Zeichen ist relativ spät dazugekommen, ansonsten finden wir noch die französischen OE-Ligaturen, und Konsonanten mit Caret. „Gänsefüßchen“ in doppelter und einfacher Ausfertigung, Trademark-Zeichen, und das Y mit Trema.

ISO-8859-1 ist absolut identisch mit Windows-1252 (das ist der gängige Alias für CP1252), nur sind eben die Zeichen 128-159 nicht definiert. Davor und dahinter sieht es jedoch völlig gleich aus.

3.3.2. ISO-8859-15 Revisited

Lange Zeit waren die Unterschiede zwischen ISO-8859-1 und Windows-1252 praktisch wenig relevant, schlicht und ergreifend, weil nicht ein Zeichen dabei war, das ohne größere Mausaktionen und Fingerverknotungen überhaupt in einen Text eingegeben werden konnte. Dann kamen die „intelligenten“ Textverarbeitungsprogramme, die z. B. in deutschen Umgebungen mit Heuristiken dafür sorgten, dass die Eingabe "Wörtliche Rede" vom Textverarbeitungsprogramm in „Wörtliche Rede“ gewandelt wurde (man vergleiche die "doppelten Anführungszeichen" mit den „deutschen Gänsefüßchen oben und unten“).

Die von Microsoft zusätzlich definierten Zeichen waren fast alle notwendig, das sah man auch im Unix-Lager ein, und spätestens mit dem Euro bestand akuter Handlungsbedarf, was die fehlenden Zeichen in ISO-8859-1 betraf. Statt aber einfach die Änderungen von Microsoft zu übernehmen (in den meisten Anwendungen hätte nicht eine Zeile Code geändert werden müssen; es hätte lediglich eines systemweiten Updates der Zeichensätze bedurft), entschied man sich aus Halsstarrigkeit, Prinzipienreiterei, Besserwisserei, Trotz oder einem guten Grund, der mir persönlich nicht bekannt ist, dafür stattdessen ein neues Codeset ISO-8859-15 zu definieren:

ISO-8859-15

ISO-8859-15

Na, endlich, der Euro war da (Nummer 164 bzw. Hex A4), auch die meisten anderen zusätzlichen Zeichen aus CP1252 wurden übernommen, aber der Bereich 128-159 wurde weiterhin freigehalten, und stattdessen wurden Zeichen aus ISO-8859-1 ersetzt. In der Theorie hatte das Unix-Lager also z. B. ein Euro-Zeichen, in der Praxis funktioniert es noch heute in den meisten (Unix-)Programmen nicht.

Der Grund dafür ist ganz einfach: ISO-8859-15 ist inkompatibel zu ISO-8859-1, und hat sich deshalb in der Praxis (noch) nicht durchgesetzt. Das wird wohl auch nie passieren, weil ISO-8859-15 auch inkompatibel zu CP1252 ist, und somit der vorher (eigentlich reibungslos funktionierende) Datenaustausch mit der Windows-Welt nicht mehr funktioniert: Vorher sahen Unix-Nutzer da, wo der Windows-Nutzer das Euro-Zeichen eingegeben hatte nur ein Fragezeichen, in die andere Richtung aber - von Unix zu Windows - wurde jedes Zeichen getreu der Intention des Schreibers wiedergegeben. Mit ISO-8859-15 wurde das Problem auf beide Richtungen ausgedehnt: Wo der Unix-Nutzer das neue Y mit Trema eingibt (Nummer 190, Hex BE) sieht der Windows-Nutzer „3/4“, die OE-Ligaturen kommen als „1/4“ bzw. „1/2“ an. Das Euro-Zeichen aus der Unix-Welt mutiert doch wieder zum Currency-Symbol, die Windows-Gänsefüßchen bleiben Unix-Fragezeichen. Und innerhalb der Unix-Welt bestehen prinzipiell die gleichen Probleme, weil sich die Programme lange Zeit uneins bleiben werden, ob sie Zeichen Nummer 164/A4 als Euro- oder Currency-Symbol interpretieren sollen.

Hätte man stattdessen die Microsoft-Erweiterungen zu ISO-8859-1 übernommen, wäre es möglich gewesen, Programme schrittweise auf die neuen Codes umzustellen (sofern das überhaupt notwendig gewesen wäre). Wie reibungslos das gehen könnte, sieht man an der Windows-Welt, in der die Euro-Einführung ohne größere Probleme vonstatten ging. Dass viele Drucker das Euro-Zeichen nicht kannten, führte nicht zu nennenswerten Irritationen, und unter Unix wird das selbst mit ISO-8859-15 noch lange Zeit üblich bleiben, weil es nicht ganz unwahrscheinlich ist, dass Dokumente, die das Euro-Zeichen verwenden, auf einem Windows-System erstellt wurden.

Fazit: Meiner Meinung nach ist ISO-8859-15 kompletter Unfug und landet hoffentlich bald auf dem Schrotthaufen der Computergeschichte.

3.3.3. Andere Sprachen, andere Windows-Codepages

Auch für nicht-westeuropäische Sprachen, die mit 8-Bit-Zeichen auskommen hat Microsoft durchweg eigene Standards definiert, oft nach der gleiche Linie wie bei ISO-8859-1/CP1252. Diese Codesets folgen durchweg dem gleichen Namensschema CPXXXX (X ist eine Ziffer von 0-9). Relativ weit verbreitet ist beispielsweise CP1251, auch als Windows-Cyrillic oder Windows-1251 bekannt. CP1251 ist ein ernsthafter Konkurrent zu KOI8-R, weil die weite Verbreitung der Microsoft-Produkte die Verwendung des Codesets natürlich stark begünstigt. Dennoch ist KOI8-R für Kyrillisch, zumindest im World Wide Web, wohl noch immer erste Wahl.

Alle Windows-Codepages sind inkompatibel zu den entsprechenden Zeichensätzen aus ISO 8859, allerdings sind die spezifischen Kompatibilitäts-Probleme für andere Sprachen weit weniger ausgeprägt. ISO-8859-1 ist ein De-Facto-Standard; die meisten Applikationen gehen bei Text, der nicht ausdrücklich gekennzeichnet ist, davon aus, dass er in ISO-8859-1 bzw. Windows-1252 kodiert ist. Ist dies (ausnahmsweise) nicht der Fall, muss ohnehin eine Zusatzinformation mitgeliefert werden, die das verwendete Codeset spezifiziert. Mit dieser Zusatzinformation wiederum erfordert es aber nicht gerade Hexenwerk, die Texte vor der Darstellung von einem Codeset ins andere zu wandeln. Auch Unix-Applikationen sind in der Regel selbstverständlich in der Lage, in Windows-Zeichensätzen kodierte Dokumente korrekt zu interpretieren. Nur müssen sie dabei natürlich wissen, um welche Windows-Codepage es sich denn dabei handelt.

3.4. Weitere Hersteller

Nicht nur Microsoft benutzt proprietäre Codesets. Hewlett-Packard verwendet für sein Unix noch immer das - zu ISO-8859-1 völlig inkompatible - Codeset HP-Roman8. Der Macintosh scheint mit Max OS X standardmäßig auf ISO-8859-1/CP1252 umgeschwenkt zu sein (erlaubt aber auch noch die alten, proprietären Mac-Codesets), NextStep verwendet eigene Codesets, selbst IBM-Mainframes mit EBCDIC (das noch nicht einmal zu ASCII kompatibel ist) sind noch in Gebrauch. Alle diese Systeme sind allerdings nicht genügend verbreitet, um das Chaos noch nennenswert zu verschlimmern, und alle haben mittlerweile Methoden entwickelt, um den Datentransfer mit dem Rest der Welt über Standard-Codesets zu gewährleisten.

3.5. Weitere Sprachen

Es gibt natürlich noch eine Reihe weiterer Sprachen, die eine überschaubare Anzahl von Schriftzeichen haben, und für die somit eigene ASCII-kompatible 8-Bit-Codesets definiert werden können. Um nicht mit ASCII in Konflikt zu kommen, ist eine Maximalzahl von 128 Zeichen möglich (die ersten 128 sind ja eben von ASCII belegt), aus ISO-8859-Sicht, maximal 96 (32 zusätzliche Control-Codes von 128-159).

Abgesehen von den diversen proprietären Codesets der Firmen Microsoft und Apple für Sprachen, die bereits behandelt wurden, sind noch einige weitere, teilweise durch Wildwuchs entstandene Codesets von Bedeutung.

3.5.1. Georgisch

Georgisch unterscheidet nicht zwischen Groß- und Kleinbuchstaben, und kommt mit 39 neuen Zeichen aus, die in eine ältere Version von CP1252 (ohne Euro, ohne Caret-Konsonanten) eingefügt wurden. Das Codeset ist als Georgian-Academy bekannt, meines Wissens allerdings nicht offiziell registriert.

3.5.2. Vietnamesisch

Vietnamesisch gehört wie Chinesisch, Japanisch, Koreanisch, etc. zu den tonalen Sprachen, Sprachen also, bei denen einsilbige Wortwurzeln (Töne) bedeutungstragend sind. Ursprünglich bediente sich das Vietnamesische der chinesischen Ideogramme. Im 13. Jahrhundert entstand daraus die Nôm-Schrift, die allerdings nur Intellektuellen verständlich war. Im 17. Jahrhundert entwickelten die christlichen Missionare das „Quôc-ngu“ („Landesschrift“), das auf dem lateinischen Alphabet aufbaut, und die Töne durch diakritische Zeichen kennzeichnet. Das Quôc-ngu löste offiziell 1910 die chinesische ideographische Schrift ab.

Vietnamesisch ist damit die einzige tonale Sprache, deren Schrift auf dem lateinischen Alphabet aufbaut (plus zwei spezielle Vokale O-Horn und U-Horn, O und U mit einem kleinen Horn rechts oben; weiterhin ein halbdurchgestrichenes D, das aus dem Polnischen bekannt ist). Es gibt allerdings insgesamt 134 Kombinationen aus diesen Grundbuchstaben und den zur tonalen Kennzeichnung dienenden diakritischen Zeichen, was bedeutet, das die von ASCII nicht definierte obere Hälfte des 8-Bit-Raumes nicht ausreichend für Vietnamesisch ist.

Die drei gebräuchlisten Codesets sind VSCII, VISCII, und VNCII (VPS). VSCII ist ein offizieller Standard, aber VISCII scheint am verbreitetsten zu sein. Alle drei Codesets haben die sechs überzähligen Zeichen im Bereich 0-31 für Control-Codes untergebracht, VSCII sogar deren zwölf, weil es auch Code-Positionen für die isolierten diakritischen Zeichen definiert.

Nach Informationen auf [Standards] sind mindestens sieben weitere Codesets in Verwendung, die allerdings nicht die Verbreitung von VSCII, VISCII und VNCII gefunden haben.

4. Multibyte-Codesets

Der Abschnitt 3.5.2, „Vietnamesisch“ ließ schon erahnen, dass viele Schriften niemals mit den maximal 256 Zeichen, die der 8-Bit-Raum erlaubt, auskommen. Richtig haarig wird es bei den CJK-Sprachen Chinesisch, Japanisch und Koreanisch, die allesamt auf die chinesische Wortschrift, die sogenannten Hanzi (Kanji auf Japanisch, Hanja auf Koreanisch) zurückgehen. Wie der Name suggeriert, entstanden diese Ideogramme während der Han-Dynastie in China, und repräsentieren - im Gegensatz zur lateinischen Schrift - nicht die Lautung, sondern die Bedeutung, was z. B eine Japanerin in gewissem Maße in die Lage versetzt, auch chinesische Texte zu verstehen.

Chinesische Schriftzeichen und ihre in Japan und Korea verwendeten Derivate sind durchweg quadratisch und wurden ursprünglich von oben nach unten und rechts nach links gesetzt. Die heutige Praxis hat sich allerdings dem lateinischen Alphabet angepasst, es wird also von links nach rechts und oben nach unten geschrieben.

4.1. CJK-Sprachen

4.1.1. Chinesisch

In chinesischen Schulen differiert der Lehrplan für das erste Schuljahr daher signifikant von dem für deutsche Grundschulen vorgesehenen, was die Erschließung des Alphabets angeht. Etwas Ordnung in das Chaos kommt, wenn man in der Lage ist, die aus Grundwörtern gebildeten Kombinationen zu deuten: Wird das Ideogramm für die Sonne über dem Ideogramm für den Horizont angeordnet, entsteht das Schriftzeichen für „früh“, zwei ineinandergeschobene Bäume werden zum Wald, das gespiegelte Schriftzeichen für einen Beamten bedeutet Fürst.

Weder die im Jahre 1892 eingeführte chinesische Lautschrift (im Gegensatz zur von der Aussprache unabhängigen Wortschrift), noch die im Jahre 1926 versuchsweise eingeführte, auf lateinischen Buchstaben aufbauende Lautschrift vermochten sich durchzusetzen. Die chinesische KP ließ die Schriftzeichen zwar vereinfachen, hielt aber an der Wortschrift fest, um eine sprachliche Zersplitterung der Volksrepublik China zu vermeiden.

4.1.2. Japanisch

Die chinesische Schrift wurde vor ca. 2400 Jahren in Japan eingeführt. Als agglutinierende Sprache entzieht sich das Japanische jedoch einer adäquaten Darstellung mit chinesischen Ideogrammen. Daher wurden ca. 250 zusätzliche Kanji mit rein phonetischer Funktion, die sogenannten Kana eingeführt, die etwa im 9. Jahrhundert zu den noch heute gebräuchlichen Katakana weiterentwickelt wurde. Ungefähr zur gleichen Zeit entstanden aus häufig auftretenden Zeichenkombinationen die Hiragana, die zur Wiedergabe japanischer Silben dienten. Heute ist die japanische Schrift eine Mischschrift aus ca. 1850 Kanji, den Hiragana und den z. B. für Fremdwörter benutzten Katakana.

4.1.3. Koreanisch

Das Koreanische ist entfernt mit dem Japanischen verwandt, und bedient sich einer Silbenschrift, die durch wiederholte Vereinfachungen aus der chinesischen Schrift hervorgegangen ist.

4.2. Escaping

Angesichts der Vielzahl der darzustellenden Schriftzeichen erscheint die Idee, die ideographischen CJK-Schriften im 8-Bit-Raum darzustellen, natürlich völlig absurd. Scheinbar reicht ein Byte mit acht Bit also spätestens in Ostasien nicht mehr zur Darstellung eines Schriftzeichens aus. Man könnte natürlich einfach mehr Bits in ein Byte packen, um einen größeren Zahlenraum zu schaffen, oder die Eins-Zu-Eins-Beziehung zwischen Bytes und Schriftzeichen aufgeben. Allerdings ist genau diese Eins-Zu-Eins-Beziehung so stark in allen Computer-Betriebssystemen verwurzelt, dass eine generelle Änderung zu enormen Schwierigkeiten führen würde.

Im Abschnitt 2.2, „Von Bits und Bytes“ wurde ja schon beschrieben, wie man es trotz 8-Bit-Bytes hinbekommt, einen Computer mit Zahlen, die weitaus größer als 256 sind, rechnen zu lassen. Man muss lediglich mehrere Bytes (2, 4, 8, ...) zu logischen Einheiten zusammenfassen. Aber auch dieser Ansatz führt zu Schwierigkeiten: Wird ASCII-Text (oder auch Text mit beliebigen 8-Bit-Zeichen) von einem „neuen“ auf ein „altes“ System übertragen, kommt auf dem alten System ein Datenstrom an, der jeweils abwechselnd aus dem Zeichen mit der Nummer Null und dem eigentlichen Zeichen aufgebaut ist. Das Zeichen mit der Nummer Null hat allerdings auf praktisch allen Betriebssystemen, eine Sonderbedeutung, die der Programmiersprache C entstammt: Das sogenannte Null-Byte kennzeichnet das Ende einer Zeichenkette. Programme hören beim ersten Null-Byte also einfach auf, einen Text zu lesen.

Wir werden später sehen, dass dieser Ansatz trotzdem verfolgt wird, er hat aber seine spezifischen Schwierigkeiten. Es gibt aber eine weitere Möglichkeit, die 256-Zeichen-Grenze auch mit 8-Bit-Zeichen zu durchbrechen, das Escaping.

Nehmen wir an, wir hätten die Aufgabe nur mit den Buchstaben des lateinischen Alphabets die deutschen Umlaute Ä, Ö, Ü, ä, ö und ü sowie das ß darzustellen. Jeder kennt den Trick, man schreibt ae, oe, ue und ss, in Computer-Lingo: Wir kodieren bestimmte deutsche Schriftzeichen mit 2 Bytes. Nicht nur für Computer ist diese Codierung aber eigentlich unbrauchbar, denn wir können jetzt nicht mehr zwischen der zuweilen vorkommenden Buchstabenkombination ae und einem ä unterscheiden. Das Wort „Masse“ wäre nur noch aus dem Zusammenhang deutbar, denn es kann sowohl für die echte Masse, als auch für Maße stehen.

Es ist aber auch eine eindeutige Codierung möglich: In der deutschen Sprache taucht der Buchstabe q nur in der Kombination qu auf. Jedes andere Vorkommen eines q ist „illegal“. Eine „kugelsichere“ Codierung könnte also so aussehen: Ein ä wird als „qa“ codiert, ein Ä als „QA“, ö entsprechend als „qo“ und ü/Ü als „qy/QY“ (um die legale Kombination qu zu vermeiden). Aus dem Eszet könnte schließlich ein „qs“ werden, nicht sehr gut lesbar, aber eindeutig.

Nachteil dieser Methode wäre, dass wir keine Wörter aus anderen Sprachen darstellen können, die unsere Restriktion für die Verwendung des q nicht kennen. Das lässt sich aber leicht ausbügeln, indem man die Konvention erweitert: Ein „echtes“ q wird als „qq“ bzw. „QQ“ dargestellt.

Wenden wir die vollständige Regel auf den letzten Absatz an, würden wir folgendes sehen:

Nachteil dieser Methode wqare, dass wir keine Wqorter aus anderen Sprachen darstellen kqonnen, die unsere Restriktion fqyr die Verwendung des qq nicht kennen. Das lqasst sich aber leicht ausbqygeln, indem man die Konvention erweitert: Ein „echtes“ qq wird als „qqqq“ bzw. „QQQQ“ dargestellt.

Lediglich die Darstellung der längeren „Q-Folgen“ erscheint etwas holprig. Ansonsten bleibt der Text aber durchaus lesbar, und selbst jemand, der unsere Konvention nicht kennt, wird das System spätestens beim zweiten Lesen verstanden haben.

Verallgemeinert lässt sich die Methode also so beschreiben: Man wählt ein (oder auch zwei) Escape-Zeichen aus, vorzugsweise eines, das in normalen Daten selten anzutreffen ist, legt eine Regel fest, dass die auf das Escape-Zeichen folgenden Zeichen eine Sonderbedeutung haben, und sorgt dafür, dass man das Escape-Zeichen noch immer darstellen kann, indem man es z. B. durch sich selber escapen lässt.

Der Trick ist ziemlich alt. In alten Drucker-Handbüchern findet man seitenweise solche Escape-Sequenzen. Wenn formatierte Textdateien ausgedruckt werden, müssen die Format-Informationen (Zeichensatz, fett, kursiv, unterstrichen, ...) ja irgendwie an den Drucker übermittelt werden. Traditionell schickte man dafür das Zeichen mit der Nummer 27 (im Bereich 0-31 für Control-Chars), gefolgt von Zeichenkombinationen, die eben im Druckerhandbuch dokumentiert waren. Dort konnte z. B. stehen, dass mit der Zeichenkombination „Zeichen Nummer 27 gefolgt von [31m“ die Schriftfarbe auf Rot gesetzt wird (bei Terminals ist das meistens sogar so: echo -e "\033[31m").

Weil das Zeichen mit der Nummer 27 so gerne für diesen Zweck eingesetzt wird, heißt es auch Escape und liegt auf der Taste Esc. Man kann die Idee aber auch noch weiterführen, und neben dem Escape-Zeichen auch noch ein Zeichen definieren, das eindeutig das Ende der Escape-Sequenz kennzeichnet. Nimmt man als Escape-Zeichen das kaufmännische Und und als Ende-Markierung das Semikolon, hat man die HTML-Autoren geläufige XML-Entity-Darstellung, bei der ein ä zu &auml; wird, und (weil das Escape-Zeichen selber immer auch in das Escaping einbezogen werden muss) zwingendermaßen die Folge &amp; für das eigentliche Kaufmanns-Und. Verwendet man als Escape-Zeichen „Kleiner-Als <“ und als Ende-Markierung „Größer-Als >“ hat man einen weiteren Weg gefunden, wie man beliebige Zusatzinformationen in einem Text unterbringen kann. Letztere Technik wird in SGML und daraus abgeleiteten Markup-Sprache wie HTML oder XML angewandt.

4.3. Multi-Byte-Encodings

Praktisch alle Kodierungen für Zeichen außerhalb des 7-Bit-Raums von ASCII bzw. des 8-Bit-Raums von Single-Byte-Codesets beruhen auf diesem Trick. Immer werden bestimmte Zeichenfolgen für die Erweiterung „missbraucht“, und die darauffolgenden Zeichen werden in einem anderen Kontext interpretiert. Der Standard ISO 8859 sieht z. B. einen Mechanismus vor, wie man durch Escape-Sequenzen aus dem 7-Bit-ASCII-Raum auf die obere Hälfte des Codesets (das die Sonderzeichen enthält) um- und wieder zurückschalten kann. Dieser Vorgang wird auch Shiften genannt.

Die meisten Kodierungen für ideographische Schriften mit mehr als 255 Zeichen gehen ähnlich vor. Gängig ist eine Definition, in der alle ASCII-Zeichen für sich selber stehen, und alle 8-Bit-Zeichen (also in ISO-8859-1 die obere Hälfte) eine Multi-Byte-Sequenz einleiten. Eine fiktive Codierung sähe so aus: Die Zeichen 0-127 entsprechen exakt ASCII und werden as is transparent durchgereicht. Hat ein Byte einen Wert im Bereich 128 bis 255 wird ein weiteres Byte gelesen und der Zahlenwert beider Bytes multipliziert.

Wieviele Zeichen könnten wir damit darstellen. 128 Zeichen (0-128) sind schon in ASCII definiert. Das erste Multi-Byte-Zeichen ist Nummer 128. Wenn es von einem Null-Byte gefolgt ist, ergäbe sich nach der obigen Regel 128 x 0 = 0, also exakt ein Null-Byte. Folgt auf ein Byte mit dem Wert 128 eins mit dem Wert 25, wird damit Zeichen Nummer 3200 erzeugt. Maximal könnten zwei Bytes mit dem Wert 256 aufeinanderfolgen. Hier würde sich der Code aus (256 - 128) x 256 = 128,

Das Verfahren wäre einfach, hätte aber etliche Nachteile (in der Praxis geht man schlauer vor). Zunächst einmal ist die Codierung nicht eindeutig, ein und dasselbe Zeichen ließe sich auf mehrfache Art und Weise darstellen. Das erscheint auf den ersten Blick harmlos, wenn es aber darum geht, einen Text nach einer bestimmten Zeichenfolge zu durchsuchen, müsste nach sämtliche Bytefolgen gesucht werden, die für diese Zeichenfolge möglich sind. Das ist ein ziemlicher Nachteil.

Ein weiteres Problem ist die fehlende Segregation der Codierung. Stoßen wir in einem Datenstrom beispielsweise auf ein Byte mit dem Wert 65, lässt sich nicht festellen, ob es dem (ASCII-)Zeichen A entspricht, oder Teil einer Multi-Byte-Sequenz ist. Dieser Mangel ließe sich beheben, indem man fordert, dass auch das zweite Byte im Bereich 128-255 liegen muss. Dann könnte man bei jedem Byte an seinem Wert erkennen, ob es Teil einer Mulit-Byte-Sequenz ist, oder aber ein ASCII-Zeichen.

Weiterhin fehlt es an einer Synchronisation. Gesetzt den Fall, wir hätten die fehlende Segregation wie beschrieben behoben, lägen alle in Multi-Byte-Sequenzen erlaubten Bytes im Bereich 128-255. Wollen wir allerdings bei einem solchen Byte feststellen, wo der Anfang, und das Ende des Multi-Byte-Zeichens ist, stehen wir auf dem Schlauch. Wir müssen von Anfang an nachzählen. Beispiel:

Am Anfang ASCII, aber dann ÄÖéä§ßßüÖÖüßß§°µäü und weiter im Text

Was ist jetzt ein Zwei-Byte-Zeichen? Die Kombination aus Grad und My, oder My und ä? In der Praxis ist das wichtig, denn dort kommen solche Situationen, in denen man einen Bytestrom verarbeiten muss (und nicht an den Anfang zurückkehren kann, um nachzuzählen) häufig vor.

Die Codierung hat aber auch einen Vorteil: ASCII-Zeichen werden transparent durchgereicht. Das ist einerseits für die Lesbarkeit wichtig, wenn ein Text vergleichsweise wenig Sonderzeichen (im Verhältnis zu ASCII) enthält. Liest man auf einer schlecht konfigurierten Web-Site das Wort „¤rchen“ (das Beispiel ist UTF-8, das fälschlicherweise als ISO-8859-1 interpretiert wird), kann man trotzdem noch erkennen, dass von einem Märchen und nicht einem Mädchen die Rede ist. Noch wichtiger wird die ASCII-Transparenz, wenn Texte von Maschinen und nicht von Menschen interpretiert wird. Maschinen/Programme springen meist auf bestimmte Schlüsselwörter an, und sehr häufig sind diese Schlüsselwörter auf die Verwendung von ASCII-Zeichen beschränkt. Werden ASCII-Zeichen von der Codierung nicht angetastet, funktionieren diese Programme weiterhin. Weitergedacht ist dies auch ein starkes Argument für die Forderung, dass Multi-Byte-Codes grundsätzlich keine ASCII-Zeichen enthalten sollten, um eine zufällige Fehlinterpretation auszuschließen.

Beherzigen wir diesen Ratschlag bei unserer Codierung, fordern wir also, dass das zweite Byte unserer Multi-Byte-Sequenzen ebenfalls immer aus dem Bereich 128-255 stammen muss (damit „opfern“ wir natürlich die Hälfte des theoretisch möglichen Wertebereichs), ist unsere Codierung auch file-system-safe. Was verbirgt sich dahinter? Hätten wir definiert, dass beispielsweise die Kombination „ä/“ für ein japanisches Hiragana stehen soll, könnten wir die Codierung nicht für die Benennung von Dateien verwenden, denn unser Dateisystem kennt unsere Codierung höchstwahrscheinlich nicht, und wird sich am Slash (/) im Dateinamen stören.

4.4. Bekannte Multi-Byte-Encodings

Gerade für den asiatischen Raum werden bereits seit langem Multi-Byte-Encodings verwendet. Diese Codierungen sind meist erheblich intelligenter als die oben beschriebene Ad-Hoc-Idee, und sind auch in Unicode-Zeiten noch sehr verbreitet. Die perfekte Codierung gibt es nicht, und so wundert es nicht, dass etliche zueinander inkompatible Kodierungen in Gebrauch sind.

Noch nicht einmal offiziell standardisiert, trotzdem weit verbreitet ist beispielsweise Big5, meist als traditionelles Chinesisch bezeichnet. Vereinfachtes (simplified) Chinesisch ist unter dem Namen GB2312 bekannt. Für Koreanisch ist eine Codierung unter dem Namen JOHAB verbreitet, für Japanisch wird oft das von Microsoft entworfene Shift-JIS verwendet.

Die sehr alten EUC-Codierungen existieren in Variationen für verschiedene Länder/Sprachen unter den Namen EUC-JP, EUC-CN, EUC-TW, EUC-KR.

Perfekt wird das Chaos dadurch gemacht, dass für fast alle Codierungen noch etliche Alias-Namen definiert sind, EUC-CN, CN-GB, csGB2312, EUCCN, EUC_CN, GB2312 bezeichnen alle ein und das selbe Codeset.

Und noch eine schlechte Nachricht: Imperia ist unicode-fähig, die oben beschriebenen Multi-Byte-Codesets sind aber eben nicht Unicode. Zur Zeit (April 2003) ist Imperia nicht in der Lage, diese Codesets korrekt zu verarbeiten (genauer gesagt: Imperia ist nicht in der Lage, zwischen solchen Codesest zu konvertieren). Um alle Imperia-Features für ostasiatische Sprachen auszunutzen, muss zur Zeit Unicode verwendet werden. Allerdings existieren etliche Tools, die Unicode in jedes noch so exotische Codeset konvertieren, so dass diese Einschränkung in der Praxis wenig Relevanz besitzt.

5. Zusammenfassung

Computer speichern Texte als Zahlenfolgen ab. Die Zuordnung von Zahlen zu Schriftzeichen wird als Codeset oder auch Charset bezeichnet, und normalerweise (8-Bit-Raum) liegen diese Zahlen im Bereich 0-255. Der allgemein anerkannte Standard ASCII legt die Zuordnung der Zeichen 0-127 fest und definiert Schriftzeichen, die zur Darstellung englischer Texte ausreichend ist. Für den Bereich der Zeichen 128-255 existiert eine Vielzahl von Standards, von den ISO-8859-1, das als Superset von ASCII zusätzlich die zur Darstellung von Texten in vielen westeuropäischen Sprachen erforderlichen Zeichen definiert, der wichtigste ist. Daneben existieren aber weitere Standards für spezielle Sprachen und spezielle Betriebssysteme.

Für Sprachen, die mehr als 256 Schriftzeichen benötigen, werden Nicht-ASCII-Schriftzeichen normalerweise in Multi-Byte-Sequenzen gespeichert. Ein konkretes Schriftzeichen wird also als Kombination von zwei oder mehr Bytes definiert.



[1] Aufgrund der zahlreichen Anfragen bei Google: Die kyrillische Zeichenfolge CCCP entpricht tatsächlich den Buchstaben SSSR - ein kyrillisches C entspricht also dem deutschen S, und das Pendant des kyrillischen P ist ein deutsches R - und steht für (krude Transliteration) Sojus Sowjetskich Sozialistitscheskich Respublik, also Union der Sozialistischen Sowjet-Republiken - UdSSR, oder englisch Union of Socialist Soviet Republics - USSR. Um gleich weiteren Fragen vorzubeugen: Ein Sowjet ist einfach ein Rat, im Sinne von Beratungsgremium. Die Sowjetunion war also eine Räterepublik. Das russische Wort Sojus (normalerweise Sajuus ausgesprochen, also mit Betonung auf der zweiten langen Silbe, das O der erste Silbe wird zu A) bedeutet Union und war Taufpate für etliche sowjetische Weltraummissionen. Mehr Info? Lernt selber Russisch! Es gibt wohl kaum eine schönere und poetischere Sprache auf diesem Planeten.

Kapitel 2. Die schöne Welt von Unicode

Der Schuldige für die babylonische Codeset-Verwirrung im Computerbereich ist leicht ausgemacht: Es ist die historisch bedingte Konvention, dass Computer Schriftzeichen intern als ein einziges Byte repräsentieren. Diese Konvention impliziert eine Beschränkung des Wertebereichs für Zeichencodes auf die Spanne 0-255, mit dieser Beschränkung lassen sich viele Sprachen dieser Welt nicht adäquat repräsentieren, und an eine parallele Verwendung mehrerer Sprachen innerhalb eines einzigen Dokumentes ist überhaupt nicht zu denken.

1. Was ist Unicode?

Die Lösung des Problems liegt auf der Hand: Der Wertebereich muss vergrößert werden. Und nichts anderes macht Unicode: Genau wie ASCII eine Standardzuordnung für die Codes mit den Nummern 0-127 vorgenommen hat, definiert Unicode eine weitere Standardzuordnung. Dem Unicode-Standard liegt dabei das ehrgeizige Ziel zugrunde, eine Standardzuordnung für jedes Schriftzeichen der Erde zu schaffen (für Schriften aus dem extraterristrischen siehe den Anhang A, Klingonisch (tIhIngan Hol)), nicht nur für echte Schriftzeichen, sondern beispielsweise auch für technische Symbole, musikalische Zeichen, Lautschrift, und viele weitere Graphiken. Es dürfte klar sein, dass der Unicode-Standard deshalb permanenten Änderungen unterworfen ist, weil auch permanent Vorschläge für die Aufnahme neuer Zeichen gemacht werden. Allerdings werden Zeichen in aller Regel zugefügt, Neu-Zuordnungen werden strikt vermieden, wodurch eine Abwärtskompatibilität des Standards sichergestellt ist.

Unicode ist übrigens auch als offizieller Standard ISO/IEC 10646 bekannt. Der Unicode-Standard wird vom Unicode Consortium, dem Zusammenschluss vieler führender Softwarehersteller und öffentlicher Einrichtungen in einer gemeinnützigen Organisation, gepflegt und weiterentwickelt. Zur Zeit aktuell ist [Unicode 3.0]; [Unicode 4.0] ist auf dem Weg und wird für den September 2003 erwartet.

Weitere wissenswerte Informationen können dem Artikel Was ist Unicode? auf [www.unicode.org] entnommen werden.

2. Der Wertebereich von Unicode

Wieviele Zeichen lassen sich mit Unicode repräsentieren? In [Unicode 3.0] sind 49.149 Zeichen enthalten, und ein Unicode-Zeichen hat eine Größe von 16 Bits (im Gegensatz zu 7 Bits für ASCII-Zeichen, oder 8 Bits für Zeichensätze wie ISO-8859-1). 16 Bits oder zwei Bytes bedeutet, dass theoretisch die Codes 0-65.535 (entspricht 65.536 Zeichen) verwendet werden können (s. Abschnitt 2.2, „Von Bits und Bytes“). 6.400 Codes sind für private Zwecke reserviert, 2 Codes sind illegal. Der UTF-16 Erweiterungs-Mechanismus (die sogenannten Surrogate) erlaubt die Definition weiterer 917.476 „offizieller“ und 131.068 privater Codepunkte.

Wieviele Zeichen ließen sich also theoretisch mit Unicode repräsentieren? Begnügen wir uns mit der Antwort: Sehr viele. Die Frage ist tatsächlich schwer zu beantworten, weil Unicode auch Zeichenkombinationen vorsieht, Möglichkeiten, die Schreibrichtung mitten im Text zu ändern, etc.

3. Unicode-Properties

Texte (nicht nur auf dem Computer) bestehen nicht nur aus einer Aneinanderreihung von Buchstaben, sondern aus einer Vielzahl von Schriftzeichen: Buchtstaben, Ziffern, Interpunktionszeichen, Steuerzeichen (Zeilenumbrüche, Tabulatoren, ...), Sonderzeichen (Prozent, Gradzeichen, Dollarzeichen), Symbolen, etc.

Dies ist in der Praxis enorm wichtig. Wird zum Beispiel ein Text für eine spätere Volltextrecherche indiziert, ist es sicherlich sinnvoll, Interpunktions- und Steuerzeichen herauszufiltern. Erwartet eine Anwendung in einer Eingabe Zahlen, muss bekannt sein, ob die eingegebenen Zeichen Ziffern repräsentieren.

Der Unicode-Standard trägt dem Rechnung, indem für jedes im Standard enthaltene Zeichen bestimmte Meta-Informationen, also Eigenschaften (Properties) gepflegt werden, die von einer Anwendung abgefragt werden können. Es lässt sich daher ermitteln, ob es sich bei einem bestimmten Unicode-Zeichen um einen Buchstaben, eine Zahl, ein Symbol, ein Interpunktionszeichen, ein Trennzeichen, eine Markierung oder ein Steuerzeichen handelt (jede dieser Kategorien hat zahlreiche Unterkategorien wie zum Beispiel Groß- und Kleinbuchstaben bei Buchstaben). Auch die Schreibrichtung - Arabisch zum Beispiel wird ja von rechts nach links geschrieben - für ein Zeichen ist abrufbar, genauso wie sich die Schriftfamilie (Lateinisch, Kyrillisch, Thailändisch, etc.) ermitteln lässt.

4. Technische Repräsentation von Unicode

Der Unicode-Standard definiert lediglich Standard-Codes für Zeichen, nicht konkrete - vom verwendeten Zeichensatz wie Times, Helvetica oder Courier abhängige Darstellungen. Genausowenig schreibt der Unicode-Standard vor, wie die Zeichencodes intern von einem Computer gespeichert oder dargestellt werden müssen.

4.1. Wide Characters

Unicode-Zeichen sind 16 Bits groß, die natürliche Repräsentation eines Unicode-Zeichens hat demnach auch 16 Bits oder 2 Bytes, und die meisten Systeme definieren heute deshalb einen Datentyp wide character, im Gegensatz zum normalen character (oft auch zum char verkürzt), der mindestens 16 Bit groß ist. Wohlgemerkt, mindestens 16 Bits, nach oben hin sind vom Standard für die Repräsentation keine Grenzen gesetzt, und deshalb sind system- oder codierungsabhängig auch 32-Bit (4 Byte-)Typen gebräuchlich.

4.1.1. Probleme mit Wide Characters

Ein Schriftzeichen wird nicht mehr durch ein Byte, sondern durch zwei Bytes dargestellt, und alle Probleme sind gelöst. Oder doch nicht? In der Praxis wirft diese Umstellung erhebliche Probleme auf, neben denen die Euro-Einführung oder die Y2K-Problematik winzig anmuten.

4.1.1.1. Auf- und Abwärtskompatibilität

Nehmen wir als Beispiel einen aus dem Zusammenhang gerissenen winzigen Textausschnitt, die Zeichenkette „schreibt über“, die von einem Programm verarbeitet werden soll. Der (Klein-)Buchstabe „s“ hat den ASCII-Code 115, das kleine „c“ hat die Nummer 99, der erste Stolperstein erwartet uns beim kleinen „ü“, von dem wir der Einfachheit halber annehmen, es sei in ISO-8859-1 codiert, habe also die Nummer 252. Insgesamt speichert der Computer die Zeichenkette als Nummernfolge 115, 99, 104, 114, 101, 105, 98, 116, 32, 252, 98, 101, 114. Ist das Programm in C geschrieben, können wir sogar noch davon ausgehen, dass das Ende der Zeichenkette durch ein Pseudo-Zeichen mit der Nummer 0 gekennzeichnet ist.

Die nächsten Überlegungen sind einfacher anzustellen, wenn wir die Nummernfolge nicht mit Dezimalzahlen (also Ziffern von 0-9), sondern mit Hexadezimalzahlen (Ziffern von 0-9 und a-f) darstellen. Es ist nicht notwendig zu verstehen, wie Hexadezimalzahlen interpretiert werden, es reicht völlig aus, zu wissen, dass sie eine andere Darstellung für exakt die gleichen Zahlen sind. In Hex sieht unsere Zeichenfolge so aus:

     s  c  h  r  e  i  b  t     ü  b  e  r
    73 63 68 72 65 69 62 74 20 fc 62 65 72
	    

Jede Zweiergruppe von (Hex-)Ziffern entspricht einem Buchstaben (das Leerzeichen Space hat den Code 30, bzw. 20 als Hexzahl).

Jetzt stellen wir unser System auf Unicode-Wide-Characters um, verbraten pro Zeichen also 2 Bytes. Wenn wir annehmen, dass unser Text in einer Datei auf der Festplatte gespeichert ist, wird diese Datei doppelt so groß, denn pro Zeichen werden jetzt doppelt so viele Bits bzw. Bytes verwendet. Leider weiß unser Programm nichts von dieser Umstellung (es muss noch umprogrammiert werden), und wird beim nächsten Leseversuch folgendes sehen:

        s     c     h     r     e     i     b     t           ü     b     e     r
    00 73 00 63 00 68 00 72 00 65 00 69 00 62 00 74 00 20 00 fc 00 62 00 65 00 72
	    

Die Zeichen wurden doppelt so groß, aus Sicht unseres noch an Bytes gewöhnten Programms wurden sie also mit Nullen aufgefüllt, obwohl noch immer der gleiche Text gemeint ist. Computerprogramme sind dumm, unser Programm macht da keine Ausnahme und wird diese Änderung einfach hinnehmen. Aber was sehen wir, wenn das Programm den Text ausgeben soll? Das hängt von Programminterna ab. Eine Möglichkeit lautet: Nichts! Weshalb? Ein Null-Byte ist in der am weitesten verbreiteten Programmiersprache, der Spache C mit der speziellen Bedeutung End Of String, also Ende der Zeichenkette belegt. Unglücklicherweise fängt unsere Unicode-Zeichenkette fast zwangsläufig schon mit genau diesem Zeichen an, und konsequenterweise gibt unser Programm jetzt eine leere Zeichenkette aus. Dieser Fall (wir sehen nichts) dürfte der häufigste sein, wenn zwei nicht-unicodefähige Programme wide characters austauschen.

Weitaus weniger wahrscheinlich ist, dass das Programm einfach über die nicht darstellbaren Null-Bytes hinweggeht, und alles andere ausgibt. Damit hätten wir erstmal keine Probleme, aber welche Länge wird unser Programm wohl für die Zeichenkette annehmen? 13 oder 26 Zeichen? Und wer weiß, an welchen anderen Stellen die Null-Bytes doch noch für Verwirrung sorgen, und Schaden anrichten?

Der häufigste Fall, wenn die Daten von einem Datenträger gelesen werden (dann gilt die Konvention mit dem Null-Byte nämlich nicht), dürfte der sein, dass das Programm die nicht-darstellbaren Null-Bytes Ersatzzeichen einfügt, wir sehen etwas wie „?s?c?h?r?e?i?b?t? ?ü?b?e?r“.

Wem das noch nicht erschreckend genug erscheint, möge sich vorstellen, dass wir Unicode jetzt richtig ausreizen wollen, und unseren Text endlich etwas weiterschreiben können: „schreibt über Anna Karenina“, wobei wir allerdings den Titel Tolstois Roman im russischen Original darstellen wollen:

Der deutsch-russische Satz richtig dargestellt

Schön wär's. Wahrscheinlicher wird uns unser Programm aber Zeichenmüll in der Art von „?s?c?h?r?e?i?b?t? ?ü?b?e?r^D?^D=^D=^D0^D ^D?^D0^D@^D5^D=^D8^D=^D0“ präsentieren. Der deutsche Part ist noch einigermaßen zu entziffern, der kyrillische Part ist ein Zeichensalat aus willkürlich anmutenden Schriftzeichen, die sich mit Steuerzeichen (meistens das ASCII-Zeichen mit der Nummer 4 End of Transmission - EOT, der Einfachheit halber durch die Zeichenfolge „^D“ ersetzt) abwechseln.

Alles nicht wünschenswert. Also werden wir zusehen, dass wir unsere Programme möglichst schnell auf Unicode umstellen, dass sie also intern alle Textdaten als wide characters erwarten. Versäumen wir es jedoch, den Rest der Welt von der Löblichkeit unseres Vorhabens zu überzeugen, wird eines Tages dennoch eine alte Datei mit 8-Bit-Zeichen den Weg in unser kleines Refugium finden. Bleiben wir bei unserem Beispiel, wir lesen die ursprüngliche, noch nicht nach Unicode konvertierte Datei:

     s  c  h  r  e  i  b  t     ü  b  e  r
    73 63 68 72 65 69 62 74 20 fc 62 65 72
	    

So war es jedenfalls einmal gemeint. Tatsächlich erwartet unser Programm aber, dass jedes Zeichen in zwei Bytes kodiert ist. Der erste Stein rollt uns jetzt in den Weg, weil wir eine ungerade Anzahl von Bytes einlesen, was nie passieren könnte, wenn wir zwei Bytes pro Zeichen verwenden. Wenn wir Pech haben (das hängt vom Talent des Programmiers ab) fliegt uns unser Programm mit Karacho um die Ohren, wenn wir Glück haben, ignoriert das Programm das überflüssige Byte am Ende oder wird wieder stillschweigend ein Ersatzzeichen darstellen, und die (einzelnen) Bytes werden jeweils zu wide characters (doppelten Bytes) zusammengefasst. Das Programm liest:

     s c  h r  e i  b t    ü  b e
    7363 6872 6569 6274 20fc 6265
	    

Hex-Zahlen haben die angenehme Eigenschaft, dass für ein Byte nie mehr als zwei „Ziffern“ gebraucht werden, und man die Bytes einfach nur zusammenschieben muss, um zu Multi-Byte-Darstellungen zu gelangen. Treudoof als Unicode interpretiert sähe unser (deutscher!) Text jetzt aber so aus:

Ostasiatische Schriftzeichen
Die Bytefolge „schreibt übe“ naiv als Unicode interpretiert

Nein, das ist nicht unser deutscher Text in japanischer Lautschrift. Noch weniger handelt es sich um eine computergestützte Übersetzung von deutsch auf japanisch. Dass hier ostasiatische Zeichen dargestellt werden, ist reiner Zufall, weil sie gerade im Bereich der falsch interpretierten Daten liegen. Tatsächlich steht hier Nonsens (hoffe ich doch jedenfalls).

All dies könnte man jedoch als Übergangsschwierigkeiten betrachten. Nach einer gewissen Zeit könnten sämtliche Softwareprogramme an die neue 16-Bit-Konvention angepasst werden, und wir wären da, wo wir hinwollen. Selbst dann wäre diese Konvention aber noch mit erheblichen Nachteilen belastet.

4.1.1.2. Speicherverbrauch

Auch jenseits allen westeuropäisch-amerikanischem Chauvinismus', ist die Tatsache nicht zu verleugnen, dass ein ganz großer Teil der (Text-)Dateien, die von Computern verarbeitet und zwischen ihnen ausgetauscht werden, mit dem 8-Bit-Codeset ISO-8859-1 (bzw. Windows-1252) kodiert ist, und diese Codierung auch für eine adäquate Darstellung geeignet ist. Viele weitere Sprachen kommen ebenfalls prinzipiell mit einem 8-Bit-Zeichensatz aus. In einer reinen Unicode-Welt, würden diese Daten plötzlich alle auf die doppelte Größe aufgebläht, würden doppelt so viel Platz auf Festplatten und im Speicher verbrauchen, würden bei der Übertragung im Netzwerk die doppelte Bandbreite verschlingen und würden auch (mindestens!) die doppelte Zeit für ihre Verarbeitung benötigen. Neben den Kompatibilitätsschwierigkeiten ist dieser Aspekt sicher der wichtigste Grund, der einer Migration von 8 nach 16 Bit für Textdaten entgegensteht.

4.1.1.3. Synchronisation

Theoretisch ließen Computer sich vollständig auf die neue 16-Bit-Konvention umstellen. Praktisch wird dies unmöglich sein. Bei Netzwerkprotokollen interessiert es beispielsweise nicht wirklich, ob es sich bei den übertragenen Daten um Text oder Bilder, Sound, Video, Programmdateien oder was auch immer handelt. Die Daten werden weiterhin als Byteströme interpretiert werden. Das gleiche gilt, wenn Daten aus Gerätedateien (Festplatten, Sound-/Grafikkarten, etc.) gelesen werden. Auch hier wird sich in absehbarer Zeit nichts ändern, und diese Vorgänge werden weiterhin byteorientiert stattfinden.

Bei Datenströmen kommt es jedoch nicht selten vor, dass der Lesevorgang irgendwo, mitten im Datenstrom beginnt oder endet. Entsprechen die Bytegrenzen gleichzeitig Zeichengrenzen ist dies kein Problem. Bei wide characters, also 2-Byte-Zeichen wird das Lesen solcher Datenströme zur Herausforderung, denn die lesende Applikation kann immer nur Paare von Bytes sinnvoll interpretieren. Kann nicht ermittelt werden, ob das erste Byte eine gerade oder ungerade Hausnummer hat, können die Daten auf zwei unterschiedliche Arten interpretiert werden, mit anderen Worten: Es kann nicht ermittelt werden, ob das erste Byte im Datenstrom das vordere oder hintere Byte eines wide characters ist.

4.1.1.4. File-System-Safety
Das Unicode-Zeichen Nummer 17210

Diesem CJK-Silbenzeichen wurde im Unicode-Standard die Nummer 17.210 (hexadezimal 0x433a) zugewiesen. Darüber werden wir uns nicht wenig freuen, bis wir auf die Idee kommen, einer Datei auf einem Windows-Rechner einen Namen zu geben, der mit diesem Zeichen beginnt. Zerlegen wir die Zahl 17.210 nämlich in zwei einzelne Bytes, erhalten wir 67 und 58, und das sind die ASCII-Codes für die Zeichen „C“ und „:“. Es bleibt eine Übungsaufgabe für die Leserin, die Unicode-Zeichenfolge zu bestimme, die (fälschlicherweise) als ASCII interpretiert C:\WINNT\system\very_important.dll ergibt.

Dies ist natürlich kein Windows-Problem. Alle Dateisysteme haben „verbotene“ Zeichen in Datei- und Verzeichnisnamen. Solange die Dateisysteme aber nicht unicodefähig sind, kann es zu bösen Überraschungen kommen, wenn eine Unicode-Byte-Folge zufällig solche verbotenen Zeichen enthält.

4.1.1.5. Was haben Eier mit Bytes zu tun?

Lemuel Gulliver, zunächst Schiffsarzt dann Kapitän auf einigen Schiffen, wurde folgendes auf seiner Reise in das Land Lilliput kolportiert (Quelle [Gulliver's Travels]):

It began upon the following Occasion. It is allowed on all Hands, that the primitive way of breaking Eggs, before we eat them, was upon the larger End: But his present Majesty's Grand-father, while he was a Boy, going to eat an Egg, and breaking it according to the ancient Practice, happened to cut one of his Fingers. Whereupon the Emperor his Father published an Edict, commanding all his Subjects, upon great Penaltys, to break the smaller End of their Eggs. The People so highly resented this Law, that our Histories tell us there have been six Rebellions raised on that account; wherein one Emperor lost his Life, and another his Crown. These civil Commotions were constantly fomented by the Monarchs of Blefuscu; and when they were quelled, the Exiles always fled for Refuge to that Empire. It is computed, that eleven thousand Persons have, at several times, suffered Death, rather than submit to break their Eggs at the smaller End. Many hundred large Volumes have been published upon this Controversy: But the books of the Big-Endians have been long forbidden, and the whole Party rendered incapable by Law of holding Employments. During the Course of these Troubles, the Emperors of Blefuscu did frequently expostulate by their Ambassadors, accusing us of making a Schism in Religion, by offending against a fundamental Doctrine of our great Prophet Lustrog, in the fifty-fourth Chapter of the Brundrecal (which is their Alcoran.) This, however, is thought to be a meer Strain upon the Text: For the Words are these: That all true Believers shall break their Eggs at the convenient End: and which is the convenient End, seems, in my humble Opinion, to be left to every Man's Conscience, or at least in the power of the Chief Magistrate to determine. Now the Big-Endian Exiles have found so much Credit in the Emperor of Blefuscu's Court, and so much private Assistance and Encouragement from their Party here at home, that a bloody War has been carried on between the two Empires for six and thirty Moons with various Success; during which time we have lost forty Capital Ships, and a much greater number of smaller Vessels, together with thirty thousand of our best Seamen and Soldiers; and the Damage received by the Enemy is reckon'd to be somewhat greater than Ours.

Gut zwei Jahrhunderte später brach ein ähnlich heftiger Glaubenskrieg um die Frage aus, wie Zahlen größer als 255 (also Zahlen, zu deren Darstellung man mehr als ein Byte braucht) intern darzustellen seien. Aus Abschnitt 2.2, „Von Bits und Bytes“ erinnern wir uns, dass der Trick prinzipiell darin besteht, diese großen Zahlen in Kombinationen von zwei, vier oder sogar acht Bytes darzustellen. So wie es nur die Ziffern 0-9 gibt, können wir dennoch Zahlen beliebiger Größe mit diesen Ziffern darstellen, wenn wir nur einfach genügend Ziffern aneinanderreihen. Die Zahl zwölf wird als Kombination aus eins und zwei dargestellt, wobei wir die erste Ziffer einfach mit zehn multiplizieren (12 = 1 x 10 + 2). Bei den Bits und Bytes gilt das gleiche, nur dass wir hier jeweils mit 256 multiplizieren müssen. Wenn wir die beiden Bytes 67 (binär 01000011) und 58 (binär 00111010) aneinanderreihen, erhalten wir also die Zahl 17.210 = 67 x 256 + 58. Oder - um bei den uns vertrauten Glühbirnen zu bleiben:

01000011 00111010
Die Zahl 17.210 in Binärdarstellung

Das scheint doch sehr klar. Oder doch nicht? Wie wäre es, wenn wir die beiden Bytes nicht von links nach rechts, sondern von rechts nach links anordnen?

00111010 01000011
17.210 binär, aber verkehrt herum?

Das erscheint zunächst ziemlich abwegig, aber es gab Hardwarehersteller, die genau diesen Weg gingen, bei Byte-Folgen also das weniger signifikante Byte (Least Significant Byte - LSB) vor das Most Significant Byte (MSB) setzten. Nein, diese Hardwarehersteller kamen nicht aus der arabischen Welt, sondern aus dem Silicon Valley in Kalifornien. Und, nein, LSB-Prozessoren sind keine exotische Ausnahme; die Intel- (oder Intel-kompatiblen) Chips, die sich in gängigen PCs finden, gehören allesamt zur LSB-Fraktion, würden die Zahl zwölf - um bei der Analogie zu bleiben - also als „21“ darstellen.

Die prominentesten Vertreter des anderen, des MSB-Lagers, sind die Prozessoren der Firmen Sun Microsystems und Motorola, sowie die meisten Prozessoren der Risc-Architecktur, und weil die Standpunkte der Verfechter der einen und der anderen Fraktion ähnlich unvereinbar, und ihre Auseinandersetzungen ähnlich unversöhnlich wie die der Big- und Little-Endians in Lilliput waren, bürgerte es sich ein, die beiden Byte-Sex- (sic! Auch dies ist ein Terminus Technicus!) Varianten als big-endian (MSB) und little-endian (LSB) zu bezeichnen. In der Praxis muss also bei jeder Zahl über 255 dazugesagt werden, welcher Konvention folgend sie denn abgespeichert ist, was einigen Rechenaufwand verursachen kann. In praktisch allen Netzwerk-Protokollen wird eine Big-Endian-Darstellung postuliert, was dazu führt, dass Little-Endian-Intel-Boxen alle Zahlen intern an den Schnittstellen zum Netzwerk drehen müssen, selbst, wenn sie unter sich bleiben.

Einigermaßen unangenehm ist es, wenn der Byte-Sex (weniger zweideutig auch als Endianness bezeichnet) von Daten nicht bekannt ist, weil dies natürlich, zu einer Ambivalenz bei der Interpretation der Daten führt. Speichern wir einen Text mit Wide Characters auf einem Intel-PC ab, und übertragen ihn auf einen Sparc-Server der Firma Sun, haben wir ein handfestes Problem, weil die beiden Rechner unterschiedliche Vorstellungen über die Interpretation der Daten haben.

4.1.2. UTF-16

Allen Schwierigkeiten zum Trotz hat die Darstellung von Unicode-Zeichen als 2-Byte-Folgen eine relativ große Verbreitung gefunden, nicht zuletzt, weil dies die native Darstellung textueller Daten in der Programmiersprache Java ist. Folge dieser Designentscheidung in Java ist ein erhöhter Speicherverbrauch, andere negative Effekte sind weniger relevant, solange es sich um ein geschlossenes System handelt, bei dem die Interpretation von Daten (Bytes) eindeutig festgelegt ist.

Tatsächlich gibt es aber zwei (weitere) Varianten von UTF-16 (16-Bit Unicode Transformation Format), nämlich eine Big-Endian- und eine Little-Endian-Variante. In Abwesenheit anderer Anhaltspunkte sollte von Big-Endianness ausgegangen werden. Ein konkreter Anhaltspunkt ist das Unicode-Zeichen mit der Nummer 65.279 (hexadezimal feff). Dieses Zeichen ist „illegal“, es ist das sogenannte Byte Order Mark - BOM.

Der Nutzen des BOM erschließt sich erst dann, wenn man sich überlegt, wie das Zeichen bei „falschem“ Byte-Sex interpretiert wird. Liest ein Big-Endian-System ein BOM aus Daten, die auf einem Little-Endian-System erzeugt wurde, sieht es nämlich nicht die Zahl 65.279 (Hex feff), sondern - da die beiden Bytes vertauscht sind - die Zahl 65.534 (Hex fffe), und das Unicode-Zeichen mit der Nummer 65.534 ist im Unicode-Standard ebenfalls als illegal gekennzeichnet. Konsequenz: Bei allen folgenden Byte-Paaren müssen die Bytes jeweils vertauscht werden, und das gilt praktischerweise sowohl für Big-Endian- als auch für Little-Endian-Systeme, was wiederum die Portabilität von Programmen auf Quelltextebene erleichtert.

Es ist nicht verwunderlich, dass das BOM normalerweise das erste Zeichen in einer Textdatei ist. Clevere Programme interpretieren es aber an beliebigen Stellen (Rationale: Die Datei könnte vom User aus Einzeldateien zusammengesetzt worden sein).

Bei den sogenannten Surrogaten handelt es sich um eine Kombination mehrerer Unicode-Zeichen, die speziell interpretiert werden, um die Beschränkung auf theoretisch maximal 65.536 Zeichen zu sprengen. In der Praxis ist dies wenig relevant, weil die Surrogate in den meisten Fonts - die ja zur endgültigen Darstellung der Textdaten notwendig sind - schlichtweg fehlen.

4.1.3. UCS-2

Die Unterschiede zwischen UTF-16 und UCS-2 sind mehr akademischer Natur. Der Name ist aus Universal Character Set und 2 Bytes zusammengesetzt.