UTF-8 plötzlich nur mehr ???
Arnold
- php
Hallo,
Ich habe ein selbst geschriebenes Forum, das mit PHP und MySQL arbeitet. Ich habe das vor etwas mehr als einem Jahr auf UTF-8 umgestellt und es lief auch problemlos.
Leider habe ich mich seitdem nicht mehr wirklich darum gekümmert und es gab in der Zwischenzeit seitens des Providers einige Updates. So läuft mittlerweile PHP 5.2.8 und MySQL 5.0.72.
PHP wird durch Version 5.2.8 ausgeführt, die MySQL Datenbank mit dem Forum ist allerdings immer noch 4.1.24.
Ich habe testweise auch einmal alles durch PHP 4.4.9 laufen lassen, Sonderzeichen werden aber weiterhin als ??? dargestellt. Das gleiche Problem tritt auch im phpmyadmin selbst auf.
Da ich mich wie gesagt nicht wirklich auf dem Laufenden gehalten habe, was die Änderungen in PHP und MySQL betrifft, habe ich momentan auch keine Ahnung wo ich bei der Fehlersuche ansetzen könnte. Hat vielleicht irgendjemand eine Idee, was da passiert sein könnte?
echo $begrüßung;
So läuft mittlerweile PHP 5.2.8 und MySQL 5.0.72.
PHP wird durch Version 5.2.8 ausgeführt, die MySQL Datenbank mit dem Forum ist allerdings immer noch 4.1.24.
Ja, was nun? 5.0.72 oder 4.1.24?
Ich habe testweise auch einmal alles durch PHP 4.4.9 laufen lassen, Sonderzeichen werden aber weiterhin als ??? dargestellt.
Der häufigste Fehler ist, die Clientverbindung nicht explizit nach dem Öffnen der Verbindung auf eine definierte Kodierung einzustellen und diese dann auch tatsächlich zu verwenden. mysql(i)_set_charset() sollte verwendet werden. Zur Not und bei ISO-8859-x und UTF-8 reicht auch ein "SET NAMES"-Statement.
Das gleiche Problem tritt auch im phpmyadmin selbst auf.
Das deutet darauf hin, dass die Daten in den Feldern nicht mit der für dieses Feld festgelegten Kodierung abgelegt sind. Ursachen kann das viele haben. Wichtig ist im Prinzip nur, dass du es in Zukunft richtig machst und die Frage, ob du die Daten retten willst. Wenn allerdings schon der PMA Fragezeichen wirft, ist höchstwahrscheinlich Handarbeit beim Datenkorrigieren angesagt.
Da ich mich wie gesagt nicht wirklich auf dem Laufenden gehalten habe, was die Änderungen in PHP und MySQL betrifft, habe ich momentan auch keine Ahnung wo ich bei der Fehlersuche ansetzen könnte.
Keine gravierenden. PHP kann immer noch nur in Ansätzen mit UTF-8 umgehen, was aber nicht ins Gewicht fällt, wenn PHP die Daten nur durchreicht und nicht bearbeitet. Und MySQL hat seit 4.1 auch keine gravierenden Änderungen in Punkto Zeichenkodierung hingelegt.
echo "$verabschiedung $name";
Ja, was nun? 5.0.72 oder 4.1.24?
Die Datenbank des Forums befindet sich noch auf Version 4.1.24, es steht aber auch Version 5.0.72 zur Verfügung. Bevor ich da aber rüberwandere möchte ich erst einmal das UTF-8 Problem in den Griff kriegen.
Das deutet darauf hin, dass die Daten in den Feldern nicht mit der für dieses Feld festgelegten Kodierung abgelegt sind. Ursachen kann das viele haben. Wichtig ist im Prinzip nur, dass du es in Zukunft richtig machst und die Frage, ob du die Daten retten willst. Wenn allerdings schon der PMA Fragezeichen wirft, ist höchstwahrscheinlich Handarbeit beim Datenkorrigieren angesagt.
Nur hat das alles noch vor einigen Monaten tadellos funktioniert. Die Daten wurden als UTF-8 in die utf8 Tabellen gelegt und waren unter phpmyadmin normal lesbar. Auch im Forum keine Probleme.
Jetzt plötzlich überall nur mehr Fragezeichen. Und ich bin mir zu 100% sicher schon seit über einem Jahr wirklich nichts mehr geändert zu haben.
Kann da theoretisch auch mein Provider etwas verpfuscht haben, oder sollte ich auf jeden Fall erstmal selbst auf Fehlersuche gehen?
echo $begrüßung;
Nur hat das alles noch vor einigen Monaten tadellos funktioniert. Die Daten wurden als UTF-8 in die utf8 Tabellen gelegt und waren unter phpmyadmin normal lesbar. Auch im Forum keine Probleme.
Dann war das vermutlich Zufall, wenn es funktioniert hat, ohne dass du dich direkt darum gekümmert hast.
Jetzt plötzlich überall nur mehr Fragezeichen. Und ich bin mir zu 100% sicher schon seit über einem Jahr wirklich nichts mehr geändert zu haben.
Dann ist es eben auch Zufall, dass es nun nicht mehr geht.
Kann da theoretisch auch mein Provider etwas verpfuscht haben, oder sollte ich auf jeden Fall erstmal selbst auf Fehlersuche gehen?
Ja, der Provider kann was geändert haben, aber diese Information nützt dir auch nicht viel weiter. Du solltest zumindest auf die Suche gehen und all das nachtragen, was zu einem reibungslosen Ablauf führt, weil ausdrücklich angegebenen ist, welche Kodierung zu verwenden ist und nicht auf irgendwelche Defaultwerte hoffen.
Die beiden wichtigsten Dinge bei der Kommunikation mir dem DBMS sind zum einen die Kodierungsangaben jedes einzelnen Feldes (Tabellen- und Datenbank-Einstellungen sind nur Defaultwerte für nehe Felder bzw. Tabellen) und die Kodierung auf der Client-Verbindung. Wie bereits erwählt mit mysql(i)_set_charset() oder SET NAMES auszuhandeln.
echo "$verabschiedung $name";
Ich habe jetzt nochmal alles nachgeprüft. Es ist wirklich alles auf utf-8 gesetzt. Der Server header, die website, die Datenbankverbindung und die Datenbankfelder selbst.
Ich bin da jetzt ziemlich mit meinem Latein am Ende.
Vor allem finde ich es seltsam, dass alte Einträge, die ja lange Zeit korrekt angezeigt wurden, plötzlich nur noch als ??? ausgegeben werden.
echo $begrüßung;
Ich habe jetzt nochmal alles nachgeprüft. Es ist wirklich alles auf utf-8 gesetzt. Der Server header, die website, die Datenbankverbindung und die Datenbankfelder selbst.
Ich bin da jetzt ziemlich mit meinem Latein am Ende.
Auf welche Weise setzt du die Kodierung der Datenbankverbindung?
Wenn du Daten aus dem Formular entgegennimmst, hast du dich vergewissert, dass sie korrekt UTF-8-kodiert sind? Wenn ja und du diese dann in ein Tabellenfeld schreibst, kann sie dann der PMA richtig anzeigen? Wenn nein, wie sieht das aus, was er zeigt?
Vor allem finde ich es seltsam, dass alte Einträge, die ja lange Zeit korrekt angezeigt wurden, plötzlich nur noch als ??? ausgegeben werden.
Mit drei Fragezeichen? Gib mal ein konkretes Beispiel!
Was spuckt MySQL auf die Aufforderung SHOW VARIABLES LIKE 'char%' aus?
echo "$verabschiedung $name";
Auf welche Weise setzt du die Kodierung der Datenbankverbindung?
Ich mache es mit SET NAMES und SET CHARACTER SET. Benutzt wird wie gesagt PHP 5.2.8, vielleicht hat das damit Probleme?
Wenn du Daten aus dem Formular entgegennimmst, hast du dich vergewissert, dass sie korrekt UTF-8-kodiert sind? Wenn ja und du diese dann in ein Tabellenfeld schreibst, kann sie dann der PMA richtig anzeigen? Wenn nein, wie sieht das aus, was er zeigt?
Das ist eine gute Frage, wie genau finde ich heraus ob die Daten korrekt kodiert sind?
Ich weiß nicht ob es hilft, aber wenn ich ein Posting mit Sonderzeichen in der Vorschau anzeigen lasse, wird alles korrekt dargestellt. Erst in der Datenbank gibts dann die Fragezeichen.
Mit drei Fragezeichen? Gib mal ein konkretes Beispiel!
Nein, es kommt für jedes eingegebene Sonderzeichen ein Fragezeichen. Wie man es halt kennt, wenn nicht der richtige Zeichensatz verwendet wird.
Was spuckt MySQL auf die Aufforderung SHOW VARIABLES LIKE 'char%' aus?
character_set_client utf8
character_set_connection utf8
character_set_database latin1
character_set_results utf8
character_set_server latin1
character_set_system utf8
character_sets_dir /usr/local/mysql/share/mysql/charsets/
echo $begrüßung;
» Auf welche Weise setzt du die Kodierung der Datenbankverbindung?
Ich mache es mit SET NAMES und SET CHARACTER SET. Benutzt wird wie gesagt PHP 5.2.8, vielleicht hat das damit Probleme?
SET NAMES und SET CHARACTER SET schließen sich gegenseitig aus, weil sie beide die selben Konfigurationsparameter setzen, nur unterschiedlich. SET CHARACTER SET will man in der Regel nur dann haben, wenn man sich seiner Auswirkungen bewusst ist und diese so haben will. Verwende lieber SET NAMES und nichts weiter! Oder noch besser die Funktion mysql(i)_set_charset().
» Wenn du Daten aus dem Formular entgegennimmst, hast du dich vergewissert, dass sie korrekt UTF-8-kodiert sind? Wenn ja und du diese dann in ein Tabellenfeld schreibst, kann sie dann der PMA richtig anzeigen? Wenn nein, wie sieht das aus, was er zeigt?
Das ist eine gute Frage, wie genau finde ich heraus ob die Daten korrekt kodiert sind?
Lass sie dir in Hex-Form ausgeben (bin2hex()) und vergleiche mit dem Sollzustand für die kritischen Zeichen. Tabellen dafür gibt es über eine Suchmaschine zu finden.
Ich weiß nicht ob es hilft, aber wenn ich ein Posting mit Sonderzeichen in der Vorschau anzeigen lasse, wird alles korrekt dargestellt.
Unter der Annahme, dass die Seite richtig kodiert und deklariert ist, wäre das richtig.
» Was spuckt MySQL auf die Aufforderung SHOW VARIABLES LIKE 'char%' aus?
character_set_database latin1
Das sieht zusammen mit dem SET CHARACTER SET sehr nach dem Übeltäter aus. Wenn die charset-Einstellung deiner Datenbank auch noch auf latin1 steht (beispielsweise weil sie den obigen Default-Wert geerbt hat), musst du dich nicht wundern, wenn es dir deine Nicht-Latin1-Zeichen kaputtmacht.
echo "$verabschiedung $name";
SET NAMES und SET CHARACTER SET schließen sich gegenseitig aus, weil sie beide die selben Konfigurationsparameter setzen, nur unterschiedlich. SET CHARACTER SET will man in der Regel nur dann haben, wenn man sich seiner Auswirkungen bewusst ist und diese so haben will. Verwende lieber SET NAMES und nichts weiter! Oder noch besser die Funktion mysql(i)_set_charset().
»» character_set_database latin1
Das sieht zusammen mit dem SET CHARACTER SET sehr nach dem Übeltäter aus. Wenn die charset-Einstellung deiner Datenbank auch noch auf latin1 steht (beispielsweise weil sie den obigen Default-Wert geerbt hat), musst du dich nicht wundern, wenn es dir deine Nicht-Latin1-Zeichen kaputtmacht.
Die Lösung war wirklich so einfach wie genial. Ich habe das SET CHARACTER SET entfernt und es funktioniert wieder. Seltsamer Weise sind aber alle alten Einträge weiterhin Ketten von Fragezeichen, die sind also wohl unwiederbringlich verloren. Ich schätze mal, da hat mein Provider irgendwas vermurkst, ich habe nämlich sicher nichts geändert.
Die Funktion mysql(i)_set_charset() habe ich mir angesehen (was bedeutet eigentlich das i in Klammern?) und auf der offiziellen PHP Seite steht, dass sie erst ab MySQL 5.0.7 verwendet werden kann. Die Datenbank liegt wie gesagt momentan noch auf version 4.1.24, ich muss vorerst also mit SET NAMES auskommen. Die Übertragung auf Version 5 ist jetzt aber der nächste Schritt, nachdem es mit UTF-8 wieder funktioniert.
Gibt es dafür vielleicht eine Seite, auf der man sieht was bei einer solchen Übertragung beachtet werden muss? Oder reicht es dafür die Datenbank zu sichern und einfach über phpmyadmin wieder in die neue Version 5 einzuspielen?
Auf jeden Fall vielen, vielen Dank für die Hilfe bisher.
echo $begrüßung;
Die Lösung war wirklich so einfach wie genial. Ich habe das SET CHARACTER SET entfernt und es funktioniert wieder. Seltsamer Weise sind aber alle alten Einträge weiterhin Ketten von Fragezeichen, die sind also wohl unwiederbringlich verloren. Ich schätze mal, da hat mein Provider irgendwas vermurkst, ich habe nämlich sicher nichts geändert.
Wenn du dir mal im MySQL-Handbuch anschaust, welche Parameter von SET CHARACTER SET auf welche Weise geändert werden und welche Auswirkungen diese Parameter haben, dann wirst du wissen, warum da nichts mehr zu retten ist, und dass der Provider unschuldig ist, wenn er es nicht war, der da SET CHARACTER SET zusammen mit der Datenbank-Kodierung Latin1 hinzugefügt hat.
Vom Client kommendes wird gemäß character_set_client interpretiert und werden vor ihrer Weiterverarbeitung nach character_set_connection umkodiert. S.C.S. setzt diesen Wert auf den Wert, der für die Datenbank konfiguriert wurde. Alle Zeichen, die in Latin1 vorhanden sind, sollten es also überlebt haben. Alle anderen können nicht nach Latin1 umkodiert werden und gehen verloren. Als Ersatz wird dann eben das Fragezeichen eingefügt.
Die Funktion mysql(i)_set_charset() habe ich mir angesehen (was bedeutet eigentlich das i in Klammern?) [...]
Es gibt schon seit längerem die MySQL Improved Extension, abgekürzt mysqli.
Gibt es dafür vielleicht eine Seite, auf der man sieht was bei einer solchen Übertragung beachtet werden muss? Oder reicht es dafür die Datenbank zu sichern und einfach über phpmyadmin wieder in die neue Version 5 einzuspielen?
Die für den Anwender einfachste Möglichkeit wird sein: Dump mit explizit angegebener Kodierung anfertigen, Dump mit explizit angegebener Kodierung ins neue System einspielen, mit phpMyAdmin Ergebnis kontrollieren.
echo "$verabschiedung $name";
Wenn du dir mal im MySQL-Handbuch anschaust, welche Parameter von SET CHARACTER SET auf welche Weise geändert werden und welche Auswirkungen diese Parameter haben, dann wirst du wissen, warum da nichts mehr zu retten ist, und dass der Provider unschuldig ist, wenn er es nicht war, der da SET CHARACTER SET zusammen mit der Datenbank-Kodierung Latin1 hinzugefügt hat.
Vom Client kommendes wird gemäß character_set_client interpretiert und werden vor ihrer Weiterverarbeitung nach character_set_connection umkodiert. S.C.S. setzt diesen Wert auf den Wert, der für die Datenbank konfiguriert wurde. Alle Zeichen, die in Latin1 vorhanden sind, sollten es also überlebt haben. Alle anderen können nicht nach Latin1 umkodiert werden und gehen verloren. Als Ersatz wird dann eben das Fragezeichen eingefügt.
Dann lag es vielleicht an einer alten PHP oder MySQL Version, als ich das eingebaut habe hat es nämlich definitiv funktioniert, auch bei anderen Leuten.
Die für den Anwender einfachste Möglichkeit wird sein: Dump mit explizit angegebener Kodierung anfertigen, Dump mit explizit angegebener Kodierung ins neue System einspielen, mit phpMyAdmin Ergebnis kontrollieren.
Kann ich dafür auch phpmyadmin verwenden? Dort finde ich nämlich nichts um den dump nochmal explizit als utf8 zu kodieren.
Oder muss ich das über Telnet machen? Davon habe ich noch weniger Ahnung. ;)
echo $begrüßung;
Dann lag es vielleicht an einer alten PHP oder MySQL Version, als ich das eingebaut habe hat es nämlich definitiv funktioniert, auch bei anderen Leuten.
Wenn die Kodierung deiner Datenbank ehemals auf utf8 stand, mussten die als UTF-8 interpretierten Daten nicht umkodiert werden. Vielleicht hat jemand die Einstellung der Datenbank geändert oder den Systemdefault-Wert. Passiert wäre dir jedenfalls nichts, wenn du nicht SET CHARACTER SET unbedacht verwendet hättest. Wie auch immer, das bringt dich jetzt auch nicht weiter. Du weißt nun jedenfalls: SET NAMES verwenden und von SET CHARACTER SET die Finger lassen.
» Die für den Anwender einfachste Möglichkeit wird sein: Dump mit explizit angegebener Kodierung anfertigen, Dump mit explizit angegebener Kodierung ins neue System einspielen, mit phpMyAdmin Ergebnis kontrollieren.
Kann ich dafür auch phpmyadmin verwenden? Dort finde ich nämlich nichts um den dump nochmal explizit als utf8 zu kodieren.
Wenn keine iconv-Extension installiert ist, bietet der PMA keine Kodierungsauswahl beim Exportieren an, macht das aber im Allgemeinen als UTF-8. Öffne zur Kontrolle die Dump-Datei mit einem Browser, stell im Menü Ansicht->(Zeichen)kodierung den Wert auf UTF-8, und wenn dann alle Umlaute und Nicht-Latin1-Zeichen (die besonders!) richtig angezeigt werden, ist der Dump UTF-8-kodiert. Beim Importieren im PMA ist in jedem Fall zur zu importierenden Datei eine Kodierungsangabe einstellbar.
echo "$verabschiedung $name";
Wenn keine iconv-Extension installiert ist, bietet der PMA keine Kodierungsauswahl beim Exportieren an, macht das aber im Allgemeinen als UTF-8. Öffne zur Kontrolle die Dump-Datei mit einem Browser, stell im Menü Ansicht->(Zeichen)kodierung den Wert auf UTF-8, und wenn dann alle Umlaute und Nicht-Latin1-Zeichen (die besonders!) richtig angezeigt werden, ist der Dump UTF-8-kodiert. Beim Importieren im PMA ist in jedem Fall zur zu importierenden Datei eine Kodierungsangabe einstellbar.
Ich habe jetzt alles in eine frische MySQL 5 Datenbank übertragen und es sieht soweit sehr gut aus.
Danke nochmals für deine Hilfe, ich hätte mir nicht gedacht, dass das so schnell wieder läuft. :)
Eine abschließende Frage zu UTF-8 habe ich noch. Ich habe diesen UTF-8 Test Text gefunden und weder im Browser, noch im Texteditor werden mir alle Zeichen korrekt angezeigt. Besonders die Runen und Braille, sowie Teile der mathematischen Formeln und der Boxen unten werden falsch/nicht dargestellt. Warum ist das so? Ich dachte wenn ein Programm UTF-8 versteht, zeigt es alle Zeichen richtig an.
echo $begrüßung;
Eine abschließende Frage zu UTF-8 habe ich noch. Ich habe diesen UTF-8 Test Text gefunden und weder im Browser, noch im Texteditor werden mir alle Zeichen korrekt angezeigt. Besonders die Runen und Braille, sowie Teile der mathematischen Formeln und der Boxen unten werden falsch/nicht dargestellt. Warum ist das so? Ich dachte wenn ein Programm UTF-8 versteht, zeigt es alle Zeichen richtig an.
Um ein Zeichen darstellen zu können, reicht es nicht nur, anhand eines Kodes das richtige Zeichen zu interpretieren, es muss auch eine Darstellungsvorschrift vorhanden sein. Für letztere sind Fonts (Schriftartdateien) zuständig. Offensichtlich fehlt dir ein solcher, der für diese Zeichen entsprechende Glyphen enthält.
echo "$verabschiedung $name";
Um ein Zeichen darstellen zu können, reicht es nicht nur, anhand eines Kodes das richtige Zeichen zu interpretieren, es muss auch eine Darstellungsvorschrift vorhanden sein. Für letztere sind Fonts (Schriftartdateien) zuständig. Offensichtlich fehlt dir ein solcher, der für diese Zeichen entsprechende Glyphen enthält.
Welche Schriftartdatei wäre dafür denn empfehlenswert?
echo $begrüßung;
Welche Schriftartdatei wäre dafür [alle Unicode-Zeichen] denn empfehlenswert?
Ich kann dich da nur auf die Wikipedia-Seite zu Unicode - Abschnitt Schriftarten verweisen oder zur Eigenrecherche animieren.
echo "$verabschiedung $name";
hi,
Da ich mich wie gesagt nicht wirklich auf dem Laufenden gehalten habe, was die Änderungen in PHP und MySQL betrifft, habe ich momentan auch keine Ahnung wo ich bei der Fehlersuche ansetzen könnte. Hat vielleicht irgendjemand eine Idee, was da passiert sein könnte?
Wenn Sonderzeichen als ? dargestellt werden, kommen diese als charset=ISO-8859-1 (latin1), der Browser wurde jedoch mit charset=utf-8 angewiesen.
Schau Dir mal den Header an, den der Webserver sendet (mit wireshark).
Hotte
echo $begrüßung;
Wenn Sonderzeichen als ? dargestellt werden, kommen diese als charset=ISO-8859-1 (latin1), der Browser wurde jedoch mit charset=utf-8 angewiesen.
Der Browser (Firefox) stellt sie in der Regel nicht als ? sondern eher als � dar. Der IE verschluckt sich daran und einige nachfolgende Zeichen.
Das ? als solches kommt beispielsweise raus, wenn man das €-Zeichen nach ISO-8859-1 zu übersetzen versucht.
echo "$verabschiedung $name";