Ankündigung

Einklappen
Keine Ankündigung bisher.

Zeichensalat trotz UTF-8

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Zeichensalat trotz UTF-8

    Hallo,
    ich habe vor vielen Jahren meine MySQL Datenbank von auf UTF-8 umgestellt. Es funktioniert seitdem auch alles wunderbar. Deutsche Umlaute, griechische oder kyrillisch Zeichen werden auf meiner Seite wie gewünscht dargestellt. Ich mache reglemäßig dumps, die ich dann in der Testumgebung bei meinem Provider oder auch auf meinem lokalen Testsystem (Xampp) einspiele. Alles funktioniert wie es soll. Nun muss ich den Provider wechseln und wollte meinen dump einspielen. Ergebnis: Alle Sonderzeichen sind zerschossen.

    Beide Datenbanken sehen eigentlich identisch aus. Bei allen Textfeldern steht Kollation 'utf8_unicode_ci'. Wenn man sich ein einzelnes Textfeld in phpMyAdmin anschaut, dann steht dort sowohl beim alten, als auch beim neuen Provider z.B. "Gewürzstämmchen". Mit dem Unterschied, dass beim alten Provider die Ausgabe auf der Webseite halt "Gewürzstämmchen" ist und beim neuen Provider weiterhin "Gewürzstämmchen".

    Ich habe nun über mein CMS einen neuen Datensatz angelegt. Auch hier habe ich wieder den Begriff "Gewürzstämmchen" gespeichert und mir die Felder per phpMyAdmin angeschaut. Ergebnis:
    • alter Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben
    • neuer Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben

    Ich dachte bislang, dass die Art der Kodierung über die Kollation festgelegt wird. Aber die ist in beiden Fällen identisch. Was muss ich tun, damit die Daten von der Datenbank des neuen Providers richtig ausgegeben werden?

    Ich bin ratlos und freue mich über jede Idee oder Lösungsansatz?

  • #2
    neuer Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben
    Dann passt es doch wenn es beim neuen Provider ok ist?!

    Ansonsten:

    Die Kollation ist dafür "fast" egal, vorsichtig gesagt.

    Wichtig(er) ist: Verbindungszeichensatz korrekt? HTTP-Header Zeichensatz korrekt? Dateien als UTF-8 gespeichert?

    Hier: https://php-de.github.io/jumpto/utf-8/#situation-1


    MOD: Verschoben von Datenbanken
    The string "()()" is not palindrom but the String "())(" is.

    Debugging: Finde DEINE Fehler selbst! | Gegen Probleme beim E-Mail-Versand | Sicheres Passwort-Hashing | Includes niemals ohne __DIR__
    PHP.de Wissenssammlung | Kein Support per PN

    Kommentar


    • #3
      Zitat von Fischfabrikant Beitrag anzeigen
      • alter Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben
      • neuer Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben
      Der Fehler liegt wohl in deiner DB, nicht beim neuen Provider. Wenn in deiner DB verstümmelte Daten wie "Gewürzstämmchen" hast solltest du das in Ordnung bringen.

      Kommentar


      • #4
        Zitat von Fischfabrikant Beitrag anzeigen
        Ich dachte bislang, dass die Art der Kodierung über die Kollation festgelegt wird.
        Das kann man ja mal nachlesen, unter den Suchmaschinen fast immer der erste Treffer
        https://de.wikipedia.org/wiki/Alphabetische_Sortierung

        Kommentar


        • #5
          Zitat von hausl Beitrag anzeigen
          Dann passt es doch wenn es beim neuen Provider ok ist?!
          Wichtig(er) ist: Verbindungszeichensatz korrekt?
          Da habe ich mich wohl unglücklich ausgedrückt, denn gerade beim neuen Provider sind bzw. waren ja die Zeichen zerschossen. Aber der Hinweis auf den Verbindungszeichensatz hat mir geholfen. Vielen Dank dafür.

          Bei meinem alten Provider sieht's aktuell so aus:
          character_set_client: latin1
          character_set_connection: latin1
          character_set_database: utf8
          character_set_results: latin1
          character_set_server: latin1
          character_set_system: utf8

          Bei meinem neuen steht überall utf8. Mit

          $dsn = 'mysql:dbname=test;host=localhost;charset=latin1';

          ist mein Problem also erstmal gelöst. Allerdings ist der Providerwechsel die Gelegenheit, die Sache auf vernünftige Beine zu stellen. Wenn ich es richtig verstanden habe, funktioniert es bei meinem alten Provider gerade so:
          • Meine Applikation gibt den Text utf8-codiert an die Datenbank
          • die Datenbank erwartet aber wegen character_set_client den Text als latin1-codiert
          • Wegen character_set_connection wird der Text latin1-codiert gespeichert. Das erklärt den Zeichensalat, wenn ich mir den Text per phpMyAdmin angucke.
          • Wegen character_set_results wird der Text dann wieder in latin1 an die Applikation übergeben. Die glaubt allerdings, es wäre utf8-codiert.
          Ist das soweit richtig? Was mir nicht klar ist: Warum sehe ich in der Textausgabe meiner Applikation keinen Zeichensalat? Umlaute, Sonderzeichen und selbst kyrillische Schrift sehen korrekt aus. Das dürfte aber nicht er Fall sein, da sie zwischenzeitlich latin1-codiert wurden.

          Kommentar


          • #6
            Wenn der gleiche Fehler sowohl beim Speichern als auch beim Laden gemacht wird, sieht der Text in der Anwendung korrekt aus. Nur in der Datenbank steht halt Müll und die Datenbank selber kann damit nicht vernünftig umgehen.

            Kommentar


            • #7
              Führe mal bei deiner Datenbank einen Wechsel zu utf8 durch.

              Als erstes schaust du mal welche Kodierung bei dir eingestellt ist mit SQL
              Code:
              SHOW CREATE TABLE tablename
              Wenn da steht charset=latin1

              Dann änderst du die DB.
              Engine sollte im übrigen Innodb sein und nicht MYISAM sonst dieses auch ändern. Siehehttps://dev.mysql.com/doc/refman/8.0/en/alter-table.html

              Die SQL Anweisung lautet
              Code:
               ALTER DATABASE databasename DEFAULT CHARACTER SET utf8mb4
              Wobei du databasename durch den Datenbanknamen deiner DB ersetzt!
              Das Statement kannst du mit phpMyAdmin oder HeidiSQL absetzen.

              Danach hast du die Daten in der DB in der richtigen Zeichenkodierung stehen. bei de Verbindung zur DB immer als charset utf8mb4 angeben.
              Sind jetzt noch verstümmelte Zeichen bei der Ausgabe vorhanden, gehst du wie in #2 und hier angeben vor.

              Kommentar


              • #8
                Zitat von Fischfabrikant Beitrag anzeigen
                ist mein Problem also erstmal gelöst. Allerdings ist der Providerwechsel die Gelegenheit, die Sache auf vernünftige Beine zu stellen. Wenn ich es richtig verstanden habe, funktioniert es bei meinem alten Provider gerade so:
                • Meine Applikation gibt den Text utf8-codiert an die Datenbank
                • die Datenbank erwartet aber wegen character_set_client den Text als latin1-codiert
                • Wegen character_set_connection wird der Text latin1-codiert gespeichert. Das erklärt den Zeichensalat, wenn ich mir den Text per phpMyAdmin angucke.
                • Wegen character_set_results wird der Text dann wieder in latin1 an die Applikation übergeben. Die glaubt allerdings, es wäre utf8-codiert.
                Ist das soweit richtig? Was mir nicht klar ist: Warum sehe ich in der Textausgabe meiner Applikation keinen Zeichensalat? Umlaute, Sonderzeichen und selbst kyrillische Schrift sehen korrekt aus. Das dürfte aber nicht er Fall sein, da sie zwischenzeitlich latin1-codiert wurden.
                Nicht ganz...

                [[character_set_client interessiert dich erstmal nicht, das ist der MySQL Client.]]
                [[Dein Script steht für den Client, hier kommt es darauf an, das es UTF-8 sein sollte. Das ist mit das wichtigste an der ganzen Geschichte.]]
                Das stimmt so nicht ganz... diese Einstellung ist wichtig.

                character_set_connection ist NUR für den Übertragungsweg!

                character_set_server ist das Default Encoding, welches verwendet wird, wenn es nicht explizit angegeben wird (z.B. beim Erstellen von Tabellen)

                character_set_results ist für die query results.

                Es ist erstmal kein Problem, einen Mischmasch aus encodings zu bilden, denn standardmässig wird nicht hin und her konvertiert. Kann man aber in den meisten Datenbanken einstellen, wie man das haben möchte.
                Ein utf8 Zeichen, das mit mehr als einem Byte kodiert ist, wird einfach "as-is" übertragen... schaut man sich den String im 1-Byte Encoding (latin1) an, sieht es "kaputt" aus. Stimmt aber nicht, denn die Daten (Bytes) sind weiterhin korrekt... ergeben aber nur in utf8 betrachtet das korrekte Zeichen.

                Genau deswegen wird dir in der Applikation alles richtig angezeigt - du hast utf8 eingekippt und bekommst auch utf8 zurückgeliefert und (!) du zeigst es in utf8 an (!)

                • alter Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben
                • neuer Provider: es wird als "Gewürzstämmchen" gespeichert und als "Gewürzstämmchen" ausgegeben
                Das ist "nur" ein Anzeigebug. "ü" sind die latin1 Zeichen für die Bytes, die in utf8 für ein "ü" stehen. Du schaust sie dir halt nur in latin1 an...

                Probier mal folgendes Query auf verschiedenen Clients aus (z.,B, ein Script, phpmyadmin, heidi/mysql workbench, CLI client). Je nach Ausgabe-Encoding sieht das anders aus...
                Code:
                select _latin1'üüü', _utf8'üüü', _cp850'üüü'
                mysql_encoding.png
                Über 90% aller Gewaltverbrechen passieren innerhalb von 24 Stunden nach dem Konsum von Brot.

                Kommentar


                • #9
                  Zitat von Fischfabrikant Beitrag anzeigen
                  Warum sehe ich in der Textausgabe meiner Applikation keinen Zeichensalat? Umlaute, Sonderzeichen und selbst kyrillische Schrift sehen korrekt aus. Das dürfte aber nicht er Fall sein, da sie zwischenzeitlich latin1-codiert wurden.
                  Nicht die Zeichen wurde hin und her kodiert, sondern der Zeichensalat. Du hast der Datenbank gesagt du sprichst ISO8859-1, aber Daten in UTF8 geschickt. Das sind für die Datenbank damit andere Zeichen (der Zeichensalat) als für dich.

                  Wenn du die Daten noch nicht gemischt hast, kannst du das fixen, indem du dir ein Dump mit ISO8859-15 Kodierung ziehst. Das was dabei rauskommt ist sauber UTF8 kodiert. Vorm Einspielen änderst du in dem Dump noch die Zeichensatzangaben von ISO8859-15 auf UTF8.

                  Kommentar

                  Lädt...
                  X