Sven Rautenberg: utf-8 und PHP und HTTP-Header des Webserver

Beitrag lesen

Moin!

UTF-8 verwendet alle 8 Bit

Stimmt.

ist Bit 7 nicht gesetzt, handelt es sich beim Zeichen sich um ein ASCII-Zeichen

Das würde ich so nicht formulieren, weil es etwas mischt, was man nicht mischen sollte.

UTF-8 ist eine Codierungsform für Unicode-Zeichen. Diese umfassen selbstverständlich auch die Zeichen, die man als ASCII-Zeichen kennt.

Das Problem deiner Mischung ist nur: ASCII ist ein für 7-Bit-Zeichen definierter, sehr eingeschränkter Zeichensatz aus 128 verschiedenen Zeichen (ein großer Anteil nicht-druckbare Sonderzeichen wie Tabulatoren, Druckersteuerungen etc. ist auch dabei).

Unicode hingegen umfaßt sämtliche Zeichen. Es ist ein Feature von UTF-8, dass es hinsichtlich der Zeichencodes für diese "ASCII-Zeichen" kompatibel ist, aber ich würde einen UTF-8-String trotzdem nicht als ASCII-String bezeichenen wollen, denn diese Tatsache ändert absolut nichts an der Behandlung solcher UTF-8-Strings.

Ein vermeintliches ASCII-Zeichen in UTF-8 ist nichts, was eine Sonderregelung erfordert - warum dann eine Sonderbezeichnung?

ASCII ist also in UTF-8 eingebettet und damit eine Untermenge davon   (ich hatte es falsch herum gesagt)

Beides richtig. :)

Ist Bit 7 gesetzt und Bit 6 nicht, dann wird das Zeichen in zwei Bytes codiert Ist Bit 7 gesetzt und Bit 6 und Bit 5 nicht, dann wird das Zeichen in drei Bytes codiert Ist Bit 7 gesetzt und Bit 6 und Bit 5 und Bit 4 nicht, dann wird das Zeichen in vier Bytes codiert

Da Bit 7 immer nur gesetzt sein kann, wenn ein Zeichen beginnt, ist UTF-8 selbstsynchoniesierend.

Das ist wieder alles falsch. Ein Multibyte-Zeichen beginnt dort, wo Bit 7 und 6 gesetzt sind. Die Folgebytes haben Bit 7 gesetzt, Bit 6 ungesetzt.

Ein Zeichen aus zwei Bytes beginnt mit 110x xxxx im ersten Byte. Ein Zeichen aus drei Bytes beginnt mit 1110 xxxx im ersten Byte. Ein Zeichen aus vier Bytes beginnt mit 1111 0xxx im ersten Byte.

Alle Folgebytes bestehen aus 10xx xxxx.

Ich will eine viersprachige Webseite bauen, die ggf. auch alle vier Sprachen gleichzeitig anzeigen können soll.

Das ist simpel.

Setzt das jetzt voraus, dass die entsprechenden Zeichensätze zur Verfügung stehen, oder unterstützen Browser, die UTF-8 interpretieren können automatisch alle darstellbaren Zeichen? Ich würde vermutren, dass nein ;-)

Das Betriebssystem benötigt natürlich einen oder mehrere Fonts, welche dafür sorgen, dass eine vernünftige Zeichendarstellung möglich wird. Dabei besteht sogar die Möglichkeit (siehe in den Opera-Zeichensatzeinstellungen), für verschiedene Unicode-Bereiche verschiedene Fonts zu verwenden - das macht der Browser aber im Allgemeinen automatisch. Hast du beispielsweise nur einen einzigen Font für chinesische Zeichen installiert und wählt "Tahoma" als Schriftart, welche kein Chinesisch kann, wird in der Regel im Stillen einfach dein einziger chinesischer Zeichensatz gewählt, wenn du chinesisch schreibst.

Mit anderen Worten: Einfach alle gewünschten Unicode-Zeichen als UTF-8 in die Seite schreiben, und sie werden in der gegebenen Reihenfolge ohne Probleme angezeigt.

Was passiert also, wenn man in UTF-8 die wilden Zeichen irgendwelcher Aliens codiert hat und nun die Seite in USA anschaut. Die kennen da ja nur sich... Soll heißen, der Alienzeichnsatz ist nicht installiert. Kommen dann die hübschen Kästchen auf den Schirm?

Klar, dann kommen Kästchen auf den Bildschirm. Der Firefox mal dort hinein IIRC sogar die Hex-Codes der Unicodezeichen, so dass man eventuell nachgucken kann.

Einerseits: Wer nicht in der Lage ist, eine ausländische Sprache zu lesen, und sich deshalb nicht drum kümmert, dessen ausländische Zeichenformen als Font zu installieren, der wird sich kaum drum kümmern, dass stattdessen die Quadrate angezeigt werden. Er könnte es ja ohnehin nicht lesen.

Andererseits: Windows liefert gewisse Fonts wie Arial durchaus als Unicodefont mit aus (welche allerdings nicht den gesamten Unicode-Zeichensatz abdecken - das wäre wohl auch etwas zuviel verlangt). Die Lage ist also nicht komplett hoffnungslos.

Mit welchem Editor und welcher Tastatur und welchen OS-Einstellungen bekomme ich denn die Alien-Texte überhaupt in die Maschine?

Du benötigst irgendetwas, was unicodefähig ist und UTF-8 speichern/senden kann.

Empfehlenswert: Dein Webbbrowser mit einer Textarea. Alternativ: "Unired" als Freeware-Unicode-Editor (mit Syntax-Highlighting), falls du diese Textarea schon mit einer Unicode-HTML-Seite zusammensetzen willst. Alternativ-alternativ: Der Windows-Notepad ab Win2000 kann auch problemlos mit Unicode umgehen.

Welchen Header sendet der Webserver für die Zeichenkodierung?

Den üblichen. UTF-8 ist äquivalent zu ISO-8859-1 oder Windows-1252 in der Headerverwendung.

Das kann ich so nicht nachvollziehen.

Soll heißen: UTF-8 erfordert im Vergleich zu den beiden anderen genannten keine Sonderbehandlung.

Als ich

<?php  ### make_utf-8.php ###

error_reporting(E_ALL); define('CRLF',chr(13).chr(10));

$text = "Die ärgerliche Straßenkrümmumg ödet uns an. Ein Ölfleck auf dem Ärmel lässt sich nicht überbügeln";

$fh = fopen('utf8-output.txt','a+'); fwrite ($fh, utf8_encode($text).CRLF); fclose($fh);

header('Content-Type: text/html; charset=UTF-8');

echo utf8_encode($text); ?>

dieses Scriptchen eben ohne den Content-Type-Header benutzt habe, und dann mit http://web-sniffer.net/?url= aufgerufen habe, kam nur Müll in der Browseranzeige an. Charset war ISO-8859-1. Genauso hatte ich es auch erwartet.

Mit dem Header hat der Browser auch artig gezeigt, was er sollte und der Web-Sniffer hat auch brav den passenden Header angezeigt (logisch).

Ja klar ist das logisch. Wenn du irgendeine Bytefolge an den Browser sendest, und ihm nicht mitteilst, welche Codierungsform den Bytes zugrunde liegt, führt das fast immer zu Müllergebnissen.

PHP könnte ein Default-Encoding mitsenden, der Browser könnte eines verwenden, oder er könnte auch per Automatik versuchen zu raten, was gesendet wurde.

Reicht es, das charset im Header zu setzen?

Scheint also der richtige Weg zu sein. Alternativ könnte man natürlich den VirtHost entsprechend konfigurieren.

Ich empfehle dringend, immer auch einen gleichlautenden Meta-Eintrag mitzusenden. Dann geht die Information "UTF-8" nicht verloren, wenn die Seite z.B. auf Festplatte abgespeichert wird.

Das kann man so pauschal nicht sagen, denn deine Strings könnten ja bereits UTF-8-codiert sein - ein Encoding wäre also falsch.

Das ist jetzt der spannende Teil. Im ersten Moment habe ich gedacht: Nö, der Sven spinnt... Aber leider spinnt der nicht, sondern mein Problem ist größer, als ursprünglich angenommen:

Wenn ich mit Templates arbeite, und mich überall auf ASCII beschränke, dann kann ich die abspeichern in was ich will (UTF-8 oder ANSI, ...). Das Bitmuster siehr überall genauso aus.

Logisch, da die Bytes von ASCII-Zeichen gleichzeitig auch gültige UTF-8-Zeichen sind.

Wenn ich nun von PHP die Platzhalter ersetzen lasse, muss ich wissen, in welcher Codierung die in der Datenbasis stehen.

Es ist schlau, sämtliche Daten in UTF-8 abzuspeichern bzw. diese EINMALIG dorthin zu konvertieren.

Um dort sinnvoll sortieren zu können, sollte die DB wissen, dass sie nun utf-8 enthält, oder?

Jein.

UTF-8 selbst besitzt die magische Eigenschaft, dass es sich als String auch ohne Kenntnis über Multibyte-Zeichen sortieren läßt - und zwar basierend auf den Zeichencodes aufsteigend.

Allerdings ist diese Sortierung nicht unbedingt die, welche für die verwendete Sprache zum Einsatz kommen sollte.

Allein im Deutschen haben wir ja schon mindestens zwei Sortierformen laut DIN:

  1. Die Umlaute ä, ö und ü werden alphabetisch wie a, o und u behandelt.
  2. Die Umlaute werden wie "ae", "oe" und "ue" behandelt.

Beide Sortierungen lassen sich mit einer schlichten, bytecodebasierten Sortierung NICHT realisieren, sondern da werden die Umlaute immer hinter das Z sortiert.

Sofern du also kompliziertere Sortierungen wünschst, mußt du einen dafür passenden Sortieralgorithmus verwenden. MySQL 4.1 erlaubt sowohl die Verwendung von UTF-8 (kann damit also wirklich etwas anfangen), als auch die Definition, nach welcher Sortierung vorgegangen werden soll (collation genannt).

Beim Arbeiten mit Flatfiles müsste es doch egal sein.

Nein, ganz und gar nicht! Auch Flatfiles produzieren, genau wie Datenbanken, lediglich Strings, die im Skript verwendet werden.

Nur wie bekomme ich Türkische Zeichen in mein Textpad?

Es gibt zwei Methoden:

  1. Du tippst die Zeichen ein.
  2. Du öffnest irgendeine Datei, in der diese Zeichen schon enthalten sind, mit dem dazu passenden Programm (beispielsweide dem Browser oder einer Textverarbeitung) und gehst beispielsweise über die Zwischenablage (Copy&Paste).

Wenn dein Textpad nicht unicodefähig ist, dann wird das aber nicht funktionieren.

Woher weiß mein Editor auf einem deutschen Computer, dass er den Zeichen-Quellcode nun plötzlich als Türksiche Zeichen interpretieren soll zum Konvertieren in utf-8 und Wegschreiben ins Flatfile?

Ein unicodefähiger Editor betrachtet sämtliche eingetippten Zeichen als Unicode-Zeichen und speichert sie intern im RAM in einer passenden Form. Dies wird wahrscheinlich NICHT als UTF-8 geschehen, sondern vielleicht als UTF-16 oder gar UTF-32 (letzteres würde ich jedenfalls machen, weil dann jedes Zeichen genau 4 Byte lang ist, und man mit den Zeichenlängen nicht ins Schleudern kommen kann).

Will man die Texte dann speichern, wird das RAM-Abbild konvertiert in die gewünschte Zeichendarstellung. Dabei kann man dann den Text sowohl als UTF-8 speichern, als auch (sofern die Zeichen da reinpassen) als ISO-8859-1 o.ä.

Beim Öffnen bestehender Texte muß man natürlich mit angeben, als was die Datei codierungsmäßig zu interpretieren ist - sofern nicht am Dateianfang die "BOM" (Byte order mark) gefunden wird, welche relativ eindeutig besagt, dass es sich um eine Unicode-Codierung handelt, und um welche.

Mit der BOM kann man eindeutig UTF-32, UTF-16 und UTF-8 auseinanderhalten, und nur wenn eine eigene Textdatei zufällig eine dieser Bytemuster am Anfang enthält (was für Texte extrem unwahrscheinlich ist, viel wahrscheinlicher ist das bei Binärdateien, die man fälschlich für Texte hält), würde diese Erkennung fehlschlagen.

Ist die Codierung dann trotzdem noch eindeutig? Welche Frage verbirgt sich hier?

Wie könnte ich es hinbekommen, innerhalb einer PHP-Quelldatei Ausgabefunktionen sowohl für Deutschen Text, als auch für Türkisch und 'Alienesisch' zu erfassen?

Wenn du UTF-8-Strings hast, ist die damit geschriebene Sprache irrelevant. Jedenfalls programmseitig.

Darf ich die Alien-Zeichen dann alle mittels "Einfügen Sonderzeichen" anreihen? Gibts Editoren, die während der Arbeit (ohne die Datei schließen zu müssen) das Umschalten des Zeichensatzes erlauben?

Du kannst deine Tastaturbelegung live umschalten. Windows zeigt dazu in der Taskleiste ein passendes Symbol an. Die ganze Chose findest du, wenn du neue Tastaturlayouts installierst.

Schön wäre dann natürlich auch das Umschalten der Tastatur. Gibt es Tastaturumschalter, die den Betrieb von mehreren Tastaturen an einem PC ermöglichen?

Keine Ahnung, aber ich schätze, dass ein simpler Tastaturumschalter allein dir nichts bringt, du wirst auch dein OS davon in Kenntnis setzen müssen, dass die Scancodes der Tastatur plötzlich anders zu interpretieren sind.

Alternativ muss man die Inhalte sonst eben wirklich alle auslagern.

Das ist doch sowieso keine schlechte Idee, oder?

- Sven Rautenberg