Nina: Reparatur von Fehlern durch Umlaute

Hallo,

habe eine latin1_swedish_ci (<-war so standard und ich habs gelassen...) Tabelle, in die Daten aus vielen kleinen XML Dateien durch ein einfaches Script, welches die Umlaute nicht ersetzte, importiert wurden innerhalb der letzten Wochen. Die urspünglichen Dateien sind nicht mehr verfügbar.
Was ich habe sind die "fehlerhaften" MySQL-Datensätze, welche mit Umlauten einfach nicht klarkommen...
Es sind also z.B. ...Persönlichkeit... zu lesen an Stelle von Persönlichkeit uvm. :-(

Gerne würde ich den Fehler (im Nachhinein) korrigieren, wenn ich nur wüsste, wie das geht.
Bitte um Hilfe, denn auch lange Suche mit Google brachte keine guten Ratschläge :-(
Vielen Dank

  1. hab so ein ähnliches problem auch gehabt, folgende lösung

    ein php skript das dir alle datensätze rausholt, und ein

    html_entities auf alle werte macht.

    danach lese ich die werte wieder aus und führe ein str_replace durch:

    $search = array("&Atilde;&curren;", "&Atilde;&para;", "&Atilde;œ","&Atilde;&frac14;","&Atilde;„","&gt;","&lt;","&quot;","&Atilde;–","&Atilde;Ÿ");
      $replace = array("ä","ö","Ü","ü","Ä",">","<",""","Ö","ß");

    $neuer_wert = str_replace($search, $replace, $alter_wert);

    und dann wieder in die datenbank einspielt.

    danach werden die werte wieder ausgelesen

    1. ein php skript das dir alle datensätze rausholt, und ein
      html_entities auf alle werte macht.

      ...

      $neuer_wert = str_replace($search, $replace, $alter_wert);

      wenn ich das richtig verstehe, müsste dazu php aber in der lage sein, die vermurksten zeichen als öäü etc zu erkennen. das bezweifle ich, da sie z.b. bei der darstellung mit phpmyadmin im stil von ö sind :-(
      oder ersetzt php das auch gleich passend?

      Danke

      1. ich hole mir ja den string aus der DB, und lasse ihn mir ja nicht anzeigen, sondern lasse ihn durch htmlentities() in html konforme sonderzeichen umsetzen, damit schaff ich mir die spezialzeichen schon mal vom hals. udn im nächsten schritt, werden die html-entitäten, wie zB &auml; durch ä ersetzt (ein echtes ä), dafür sorgt dann str_replace mit den such udn ersetzarrays $search und $replace. man kann das natürlich auch in einem schritt machen mit

        $neuer_string = str_replace($search, $replace, htmlentities($alter_string));

        1. auch wenn ich irgendwie nicht ganz glaube, dass php selbst drauf kommt, dass die sonderzeichen ein ä sein sollen und es somit mit &auml; ersetzt, was mir die arbeit erleichtert, werd ich es mal versuchen.
          Danke schonmal für die hilfe!

          1. hi,

            auch wenn ich irgendwie nicht ganz glaube, dass php selbst drauf kommt, dass die sonderzeichen ein ä sein sollen

            Kommt es bei Christians Methode ja auch nicht - er wandelt nicht "ä" in "ä" um, sondern "&Atilde;&curren;" in "ä".

            Nur den Umweg über htmlentities könnte er sich dabei eigentlich sparen, wenn er direkt die beiden Zeichen in ein ä umwandeln liesse.

            Und generell kann man sich so einen Umwandlungszirkus natürlich sparen, wenn an sich über Zeichenkodierungen mal Gedanken macht, bevor das Kind in den Brunnen gefallen ist.

            gruß,
            wahsaga

            --
            /voodoo.css:
            #GeorgeWBush { position:absolute; bottom:-6ft; }
            1. Seid gegrüßt!

              Und generell kann man sich so einen Umwandlungszirkus natürlich sparen, wenn an sich über Zeichenkodierungen mal Gedanken macht, bevor das Kind in den Brunnen gefallen ist.

              Gut das versuch ich jetz mal (eigentlich isses auch bei mir schon so weit): wie umgehen ich den ganzen Zirkus?

              Ich nehme meine Werte aus ner <textarea> (utf-8) und setze die per
              INSERT in ne mysql tabelle?
              Was sollte ich vorher mit den Werten noch tun, mal abgesehen von htmlentities() und htmlspecialchars()?

              Danke schön.

              --
              Bis Später

              ==========================================================
              Testversion meiner Seite
              1. echo $begrüßung;

                Ich nehme meine Werte aus ner <textarea> (utf-8) und setze die per
                INSERT in ne mysql tabelle?
                Was sollte ich vorher mit den Werten noch tun, mal abgesehen von htmlentities() und htmlspecialchars()?

                Nichts anderes als mysql_real_escape_string(). In einer Datenbank hat keinerlei ausgaberelevante Formatierung etwas zu suchen. Sonst funktionieren solche Dinge wie Sortieren und Suchen nicht mehr. Gleich nach dem Verbindungsaufbau teilst du dem MySQL-Server mit, in welcher Zeichenkodierung du mit ihm zu sprechen wünschst. In deinem Fall
                  SET NAMES utf8
                Es ist dabei erst einmal unerheblich, welche Kodierung beim Anlegen der Tabelle für die Felder angegeben wurde. MySQL nimmt gegebenenfalls Umwandlungen vor. Natürlich sollte man dabei beachten, dass nicht von jeder Kodierung in jede andere Kodierung verlustfrei umgewandelt werden kann.

                MySQL-Handbuch Kapitel Character Set Support. Speziell für die Verbindungen zwischen Client und Server gilt Kapitel Connection Character Sets and Collations

                Obiger Text gilt ab MySQL-Version 4.1.

                echo "$verabschiedung $name";

                1. Seid gegrüßt!

                  Ich bedanke mich vielmals.

                  --
                  Bis Später

                  ==========================================================
                  Testversion meiner Seite
          2. auch wenn ich irgendwie nicht ganz glaube, dass php selbst drauf kommt, dass die sonderzeichen ein ä sein sollen und es somit mit &auml; ersetzt, was mir die arbeit erleichtert, werd ich es mal versuchen.

            php nimmt einfach den string her und ersetzt die sonerzeichen, und damit alle sonderzeichen, in &werte.

            hier der code (die datenbankverbindung wird mit adodb hergestellt)

            include("inc/database.inc.php");
            $sql = "SELECT * FROM phonecalls";
            $rs = $db->GetArray($sql);
            foreach($rs as $rss)
            {
              $id = $rss['NUMMER'];
              $desk =  htmlentities($rss['DESK']);
              $person = htmlentities($rss['PERSON']);
              $text = htmlentities($rss['TEXT']);
              $mail = htmlentities($rss['EMAIL']);
              $sql = "UPDATE phonecalls SET DESK = '".$desk."',
                                            PERSON = '".$person."',
                                            TEXT = '".$text."',
                                            EMAIL = '".$mail."'
                                            WHERE NUMMER = ".$id;
              $rs = $db->Execute($sql);
            }
            $rs = $db->GetArray($sql);
            foreach($rs as $rss)
            {
              $id = $rss['NUMMER'];

            $desk = $rss['DESK'];
              $person = $rss['PERSON'];
              $text = $rss['TEXT'];
              $mail = $rss['EMAIL'];
              $search = array("&Atilde;&curren;", "&Atilde;&para;", "&Atilde;œ","&Atilde;&frac14;","&Atilde;„","&gt;","&lt;","&quot;","&Atilde;–","&Atilde;Ÿ");
              $replace = array("ä","ö","Ü","ü","Ä",">","<",""","Ö","ß");

            $desk = str_replace($search, $replace ,$desk);
              $person = str_replace($search, $replace ,$person);
              $text = str_replace($search, $replace ,$text);
              $mail = str_replace($search, $replace, $mail);

            $sql = "UPDATE phonecalls SET DESK = '".$desk."',
                                            PERSON = '".$person."',
                                            TEXT = '".$text."',
                                            EMAIL = '".$mail."'
                                            WHERE NUMMER = ".$id;
              $rs = $db->Execute($sql);
            }

            Danke schonmal für die hilfe!

            gerne :-)

            1. super. danke.
              hat mit den meisten Datensätzen geklappt.
              Doch was in diesem Fall:
              "nach dem Öffnen zum Zwangsbeenden. Möglicherweise sind Umlaute oder Sonderzeichen die Übeltäter."

    2. echo $begrüßung;

      hab so ein ähnliches problem auch gehabt, folgende lösung

      Deine Methode hat den Nachteil, dass sie nur einige wenige handverlesene Zeichen erwischt. Außerdem ist sie besonders umständlich. PHP kennt auch Funktionen wie utf8decode().

      echo "$verabschiedung $name";

  2. echo $begrüßung;

    habe eine latin1_swedish_ci [...] Tabelle, in die Daten aus vielen kleinen XML Dateien durch ein einfaches Script, welches die Umlaute nicht ersetzte

    Das Feld (oder auch mehrere) enthält nun UTF-8-kodierte Daten und ist aber als ISO-8859-1/latin1 deklariert. Die folgende Methode funktioniert nur, wenn das in der gesamten Datenbank so ist. Sind einzelne Datensätze doch richtig kodiert, dann bekommst du diesen Kuddelmuddel sicher nur per Hand vernünftig ausklamüsert.

    Als ersten eine Datensicherung des jetzigen Bestands anfertigen. Nicht dass am Ende noch mehr und unwiederbringlich versaut ist. (Mit phpMyAdmin die Datenbank oder Tabelle in eine zweite kopieren reicht aus.)

    UPDATE test SET feld1 = CONVERT( BINARY feld1 USING utf8 ), feld2 = CONVERT( BINARY feld2 USING utf8 ), ...;

    Für jedes betroffene Feld ist eine solche CONVERT-Funktion zu notieren. Numerische und BLOB-Felder sind davon auszunehmen.

    "BINARY feldname" liest die Daten aus dem Feld so wie sie sind und nimmt dabei keine Konvertierung vor.
    CONVERT( daten USING neue_kodierung ) konvertiert "daten" aus der vorliegenden Kodierung nach "neue_kodierung". Da es vorher Binär-Daten waren (Schlüsselwort BINARY), wird auch hier keine Konvertierung vorgenommen. Ergebnis ist aber ein UTF-8-String, der auch als solcher ausgezeichnet ist.
    Beim Schreiben der Daten in das Feld stellt MySQL fest, dass es einen UTF-8-String in ein mit latin1 ausgezeichnetes Feld schreiben soll und nimmt daraufhin eine Konvertierung nach latin1 vor.

    z.B. ...Persönlichkeit...

    Das ist übrigens keine ordentliche Kodierung. Das  gehört da nicht hin, wenn es sich um ein mit ISO-8859-1 interpretiertes UTF-8-ö handeln soll.

    echo "$verabschiedung $name";

    1. echo $begrüßung;

      Nachtrag:
      Eine Umwandlung von UTF-8 nach ISO-8859-1/latin1 kann selbstverständlich nur die Zeichen berücksichtigen, die sich mit ISO-8859-1 darstellen lassen. Waren in den ursprünglichen Daten Zeichen außerhalb von ISO-8859-1 enthalten, beispielsweise das Euro-Zeichen € oder typografisch richtige „Anführungszeichen“, gibt es nun eine Ersatzdarstellung in Form eines ?. Das ursprüngliche Zeichen lässt sich daraus nicht wieder herstellen.
      In dem Fall solltest du dir überlegen, ob nicht UTF-8 die passendere Kodierung der Felder ist. Außerdem wäre dann der Änderungsvorgang etwas komplizierter: Es müsste zunächst eine zweite Tabelle angelegt werden, deren Felder auf eine UTF-8-Kollation eingestellt werden. Es ist nun kein UPDATE sondern ein
        INSERT INTO neue_tabelle SELECT CONVERT(...), CONVERT(...), blobfeld, numerisches_feld FROM alte_tabelle
      zu verwenden.

      echo "$verabschiedung $name";