Wann wird wo encodet?

Wann wird wo encodet?

am 04.12.2006 20:24:06 von official

Hallo Gemeinde,

Ich hab so leichte Verständnisprobleme, wann wo was encoded wird.

Ich betreibe die Seite www.ufra-schach-jugend.de. Unter Turniere muss ich
regelmäßig Turniertabellen veröffentlichen. Die werden mit einem
Windows-Programm erstellt und als latin1-Text exportiert, danach mit recode
nach utf-8 gewandelt. So weit, so gut.

Lokal bleibt alles bei utf-8. Das funktioniert wunderbar. Die Textdatei wird
per Browser in ein PHP-Skript eingelesen, das die Tabelle parst. Dann legt
das Skript eine MySQL-Tabelle an und schreibt die Daten hinein. Andere
Skripte lesen die MySQL-Tabellen wieder aus und geben schön (glaub ich
zumindest) formatierte Tabellen aus.

Eine Kontrolle zeigt:

mysql> select name, hex(name) from a where nr=4;
+--------------+--------------------------+
| name | hex(name) |
+--------------+--------------------------+
| Müller, Max | 4DC3BC6C6C65722C204D6178 |
+--------------+--------------------------+
1 row in set (0.00 sec)

C3BC für ü sieht ganz vernünftig aus. Die Konsole ist auf utf-8
gestellt und zeigt den Umlaut ebenfalls korrekt an. Ebenso sind die Umlaute
in den Ausgabescripten korrekt dargestellt.

Jetzt das gleiche in der "Produktion". Hier ist die locale latin1. alles
andere ist utf-8: die mysql-Tabellen und Datenbanken, apache serviert auch
als utf-8. Die Skripten werden unverändert hochgeladen. Die gleiche
Textdatei wird von hier aus per Browser in das PHP-Script auf dem Server
eingelesen, das schreibt sie in die MySQL-Tabelle. Die anderen Skripte
lesen die Tabellen wieder aus, und die Umlaute werden korrekt angezeigt.

Aber:

mysql> select name, hex(name) from a where nr=4;
+--------------+------------------------------+
| name | hex(name) |
+--------------+------------------------------+
| Müller, Max | 4DC383C2BC6C6C65722C204D6178 |
+--------------+------------------------------+
1 row in set (0.00 sec)

Das ü ist jetzt C383C2BC, der Umlaut wird auf der latin1-Konsole falsch
dargestellt, auf der utf-8-Konsole aber richtig.

Ich habe irgendwie den Eindruck, dass die utf-8-Textdatei als latin1
aufgefasst und nach utf8 gewandelt wird und dass das beim Ausgeben wieder
rückgängig gemacht wird. Das führt dazu, dass der mysqldump nicht portabel
ist (wofür mysqldump nix kann). Und da ich demnächst wohl den Server
wechlse, ist das recht ärgerlich.

Ein- und Ausgabeskripte verwenden PEAR::HTML_Template_Sigma.

Wie schaffe ich es, dass in der Tabelle die echten utf8-Codes stehen und
auch richtig interpretiert werden?

Ich vermute mal, dass der Fehler im Zusammenspiel von MySQL und PHP
entsteht, bin mir aber nicht sicher, daher Xpost & F'up.

mfg
Christian

--
When I die, I want to die like my Grandmother who died peacefully
in her sleep. Not screaming like all the passengers in her car.

Re: Wann wird wo encodet?

am 05.12.2006 01:11:11 von Hadanite Marasek

> Jetzt das gleiche in der "Produktion". Hier ist die locale latin1. alles
> andere ist utf-8: die mysql-Tabellen und Datenbanken, apache serviert auch
> als utf-8. Die Skripten werden unverändert hochgeladen. Die gleiche
> Textdatei wird von hier aus per Browser in das PHP-Script auf dem Server
> eingelesen, das schreibt sie in die MySQL-Tabelle. Die anderen Skripte
> lesen die Tabellen wieder aus, und die Umlaute werden korrekt angezeigt.
>
> Aber:
>
> mysql> select name, hex(name) from a where nr=4;
> +--------------+------------------------------+
> | name | hex(name) |
> +--------------+------------------------------+
> | Müller, Max | 4DC383C2BC6C6C65722C204D6178 |
> +--------------+------------------------------+
> 1 row in set (0.00 sec)
>
> Das ü ist jetzt C383C2BC, der Umlaut wird auf der latin1-Konsole falsch
> dargestellt, auf der utf-8-Konsole aber richtig.

Darüber bin ich auch schon gestolpert, der Fehler ist etwas fies. Du
musst zwei queries "SET CHARACTER SET UTF8" und "SET NAMES UTF8"
abschicken, nachdem Du Dich PHP-seitig mit der Datenbank verbunden hast.
Denn standardmässig ist die Verbindungseinstellung latin1, d. h. mysql
geht davon aus, dass da Daten in latin1 rübergepumpt werden, muss sie
aber als UTF8 speichern, wandelt sie on the fly um.
ü in UTF8 ist C3BC, er (oder sie? ;-)) glaubt aber, es sei latin1 und
macht aus C3 C383 und aus BC C2BC.
Da der Fehler bei der Ausgabe erneut gemacht wird, heben sich beide
Fehler auf, und Du hast keine Probleme bis auf das Müller in der
Datenbank 9 anstatt 7 Bytes belegt...

Um das ganze schnell rückgängig zu machen, machst Du z. B. zwei seperate
Verbindungen zur Datenbank auf und setzt die zweite auf utf8, wie oben
beschrieben. Dann holen (Daten werden umgewandelt von fake-utf8 zu
richtigem utf8) und mit der zweiten Verbindung "UPDATE ... WHERE
= Wert", dann werden die Daten neu und korrekt als
UTF8 in die Datenbank geschrieben.

Geht sicher auch anders, Grundprinzip ist das gleiche (mit latin1 lesen
und utf8 schreiben). Sei vorsichtig (Backup machen)!

Re: Wann wird wo encodet?

am 05.12.2006 01:59:35 von Oliver Block

Christian H. Kuhn wrote:

> Das ü ist jetzt C383C2BC, der Umlaut wird auf der latin1-Konsole
> falsch dargestellt, auf der utf-8-Konsole aber richtig.

Doppelt nach UTF-8 konvertiert:

C3 = 11000011

Nach UTF-8 konvertiert: 11000011 10000011 = C3 83

BC = 10111100

Nach UTF-8 konvertiert: 11000010 10111100 = C2 BC

Wann das geschieht, kann ich Dir nicht sagen. Schau Dir den Code an.
Verwendest Du MySQL 5.x? Dann kannst Du das Client-Encoding einstellen. Es
gibt wohl auch noch ein Verbindungsencoding, aber da bin ich mir nicht ganz
sicher.

Gruß,

Oliver

Re: Wann wird wo encodet?

am 05.12.2006 12:07:19 von phpmyforum

On Dec 4, 8:24 pm, "Christian H. Kuhn" wrote:
> Jetzt das gleiche in der "Produktion". Hier ist die locale latin1. alles
> andere ist utf-8: die mysql-Tabellen und Datenbanken, apache serviert auch
> als utf-8. Die Skripten werden unverändert hochgeladen. Die gleiche
> Textdatei wird von hier aus per Browser in das PHP-Script auf dem Server
> eingelesen, das schreibt sie in die MySQL-Tabelle. Die anderen Skripte
> lesen die Tabellen wieder aus, und die Umlaute werden korrekt angezeigt.

Da alles richtig angezeigt wird, gehe ich erstmal davon aus, das alles
richtig in der DB gespeichert wurde.



> Aber:
>
> mysql> select name, hex(name) from a where nr=3D4;
> +--------------+------------------------------+
> | name | hex(name) |
> +--------------+------------------------------+
> | Müller, Max | 4DC383C2BC6C6C65722C204D6178 |
> +--------------+------------------------------+
> 1 row in set (0.00 sec)
>
> Das ü ist jetzt C383C2BC, der Umlaut wird auf der latin1-Konsole fal=
sch
> dargestellt, auf der utf-8-Konsole aber richtig.

Wie du schon richtig sagst: __latin1-Konsole__ !!!

Somit musst du dem mysql-client sagen welchen Zeichensatz er nehmen
soll.

Gruß