Tim: UTF-8 ISO MIX Wie erkennen und anpassen

Hi,

Ich experimentiere gerade mit einigen Tools,die auch in vielen CMS verwendet werdet. Also Module, wie Bildergalerien, Wetterdaten, usw...

Alle haben eines gemein, sie werden per file_get_contents reingezogen. Das bedeutet aber auch die jeweilige Formatierung, bei einigen UTF-8 bei anderen iso.

Das dumme ist ja leider ich kann jetzt nicht präventiv alles mit utf8_encode sicherheitshalber alles darim umwandeln, denn das verträgt ja unsinnigerweise bereits utf-8 codiertes nicht.

Daher vermute ich, wäre schön wenn ich mich irre(?), das ich erst mal den jeweiligen Content testen muss welche Codierung vorliegt, um dann entsprechend das Ganze auf einen Nennen zu bekommen. Aber wie finde ich das raus?

Was muss ich tun?

Tim

  1. Hello,

    Was muss ich tun?

    Das Archiv durchsuchen.

    Ich hatte da schon mal das gleiche Problem und habe damals eine Menge brauchbare Vorschläge bekommen.
    Leider habe ich die Lösungen nicht hier...
    Also suche bitte selber mal im Archiv.

    Aufgabe war damals: UTF-8 automatisch erkennen und die Lauflänge (Anzahl fer Bytes) des jeweiligen Zeichens bestimmen.

    Liebe Grüße aus Syburg bei Dortmund

    Tom vom Berg

    --
    Nur selber lernen macht schlau
    http://bergpost.annerschbarrich.de
    1. Hi Tom,

      Was muss ich tun?

      Das Archiv durchsuchen.

      Na ja sofern meine These richtig ist, aber meine erste Frage war ja ob das nicht einfacher gehen kann.

      Aufgabe war damals: UTF-8 automatisch erkennen und die Lauflänge (Anzahl fer Bytes) des jeweiligen Zeichens bestimmen.

      Danke, meinst du das?
      http://forum.de.selfhtml.org/archiv/2008/9/t176846/#m1164170

      Ja, jetzt wird es kurios.

      Zunächst habe ich, wie du auch, mb_detect_encoding() probiert.
      Dann bekomme ich bei 3 verschiedenen Inhalten als Rückgabe UTF-8, kann aber nicht denn je nach Einstellung der Browsercodierung oder wahlweise der HTML Bestimmung, erhalte ich bei 2en lesbares und beim dritten Hieroglyphen, oder eben umgekehrt.

      Nun habe ich die Funktion valid_utf8() probiert, da bekomme ich dann tatsächlich 2 = false, 1= utf-8 "3". Wobei ich nicht ganz verstehe was mit den leveln 1-4 gemeint ist.

      So nun zurück zu meinem Problem. Bedeutet das nun wenn es kein UTF-8 ist ist es automatisch iso bzw. kann ich falls FALSE unbesorgt utf8_encode anwenden?

      Gruss
      Tim

      1. Hello Tim,

        Danke, meinst du das?
        http://forum.de.selfhtml.org/archiv/2008/9/t176846/#m1164170

        ja, das war wohl der zusammenfassende Thread.
        Cybaer hatte diese Funktion geschrieben, weil er genauso wie ich, schon früher auf die Fragestellung  gestoßen war.

        Die "Level" kennzeichnen lediglich, ob in dem untersuchten Text gültige UTF-8-Sequenzen mit 1, 2, 3, oder gar vier Bytes vorkommen. False wird geliefert, sowie eine ungültige Sequenz auftritt.

        UTF-8 ist im Prinzip resynchronisierbar, d.h. dass mann das vermeintlich erste Byte einer UTF-8-Sequenz erkennen kann und dann einfach nur feststellen muss, ob die folgenden dazu passen.

        Es könnte sich natürlich immer noch um eine lose Bytefolge, also keine lesbaren Texte, handeln.

        Eine wirklich sichere Erkennung, ob es sich um UTF-8 handelt, gibt es also nicht, aber man kann zumindest sagen, wenn ein Text kein gültiges UTF-8 ist, bzw. zumindest nicht durchgängig.

        Schau Dir mal auf Wikipedia die Erklärungen dazu an.

        http://de.wikipedia.org/wiki/UTF-8

        Liebe Grüße aus Syburg bei Dortmund

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hi Tom,

          danke für deine Erläuterungen. Leider bleibt meine wichtigste Frage unbeantwortet:

          Ein Content gibt sich als UTF-8 aus mit der Funktion mb_detect_encoding(), während Cybaers Funktion das richtigerweise als falsch entlarvt.

          Was ist nun zu tun, kann ich das jetzt bedenkenlos umwandeln oder ist mit Problemen zu rechnen?

          Schau Dir mal auf Wikipedia die Erklärungen dazu an.

          http://de.wikipedia.org/wiki/UTF-8

          Davon verstehe ich, aufgrund mangelnder Grundkenntnisse, so gut wie nix.
          Auch mich jetzt eine Woche in Unicode,Byteformatierungen, usw. einzulesen wäre fatal, weil so habe ich das schon zu oft gemacht: Man macht etwas, ein kleines Problem taucht auf, man sucht die Lösung, arbeitet sich in diese fremde Materie ein, findet womöglich noch andere Aspekte die interessant sein könnten und am Ende weiss man nicht mehr das eigentliche Projekt zu fokussieren, weil irgendwie zuviel vergessen. Zumal keiner einer Experte auf allen Gebieten sein kann, auch wenn das oft hier im Forum gefordert wird. Hat jetzt aber nichts mit deiner Antwort zu tun, die war schon sehr hilfreich, so kam ich zu cybaers Funktion.

          Gruss
          Tim

          1. Hello,

            das Problem steckt eventuell darin, dass einzelne Zeichen nicht richtig codiert wurden.
            Dann kommt eine Umwandlungsfunktion, die den Text als Ganzes fokussiert, sicherlich aus dem Tritt.

            Das kommt z.B. dann vor, wenn ein Text bereits in UTF-8 codiert war und dann aus Unkenntnis als ASCII oder ISO-8859-1 geöffnet und weiterbearbeitet wurde, aber trotzdem als UTF-8 wieder abgespeichert. Das hört sich jetzt wirr an, kommt aber leider in der Praxis immer wieder gerne vor.

            MMn ist das der Fluch der Automatik. Die User wissen gar nicht mehr, was da so alles im Hintergrund passiert und normalerweise erkennt ein neuerer Editor UTF-8 auch an der vorangestellten BOM. Fehlt diese aber, nimmt er eben seine Voreintellung. Der User aber merkt beim Abspeichern, dass er ja UTF-8 speichern wollte und hat somit doppelt codiert. Wenn nun im betrachteten Abschnitt keine Zeichen größer #127 vorhanden waren, fällt es ihm auch nicht auf. Je nach Editor wird aber die ganze Datei durch den Konverter geschickt, oder aber nur der bearbeitete Abschnitt.

            UTF-8 wird uns noch viel Kummer bereiten.

            Liebe Grüße aus Syburg bei Dortmund

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. echo $begrüßung;

              UTF-8 wird uns noch viel Kummer bereiten.

              Nicht weniger als das bisherige Kodierungschaos. Zu keiner Zeit gab es einen Mechanismus, der die verwendete Kodierung zu einem Text abspeicherte. Jedenfalls nichts, das sich in irgendeiner Weise globalgalaktisch durchgesetzt hätte. Das Problem, Zeichen zu missinterpretieren oder durch falsch angewendete Umkodierungen unbrauchbar zu machen, wird es immer geben, wenn zwei verschiedene Kodierungen aufeinandertreffen. UTF-8 und seine Kollegen lösen wenigstens langfristig das bisherige Chaos auf. Im Idealfall werden nach der unvermeidlichen Übergangsphase alle Nicht-UTF-8-Systeme aus der praktischen Relevanz verschwunden sein. Bis dahin heißt es, sich mit dem nicht wirklich schwierigen Thema auseinanderzusetzen, genauso wie man die herkömmlichen Kodierungssysteme zu beachten hatten.

              echo "$verabschiedung $name";

              1. Hi,

                ...UTF-8 und seine Kollegen lösen wenigstens langfristig das bisherige Chaos auf. Im Idealfall werden nach der unvermeidlichen Übergangsphase alle Nicht-UTF-8-Systeme aus der praktischen Relevanz verschwunden sein.

                Weil mich dieses Chaos nervt, denke ich jetzt darüber nach alles auf UTF-8 umzustellen, Ausgabeseiten, Mysql.

                Aber macht das Sinn? oder kommt dann wieder irgendeine anderere Codierung die dann Hip ist?

                Muss zugeben, das mich das ganze Thema ein wenig überfordert, das war noch schön als man nicht drüber nachdenken musste und alles machte der Browser alleine.

                Vor allem macht mir ein Gedanke Kopfschmerzen, müssen die Scripte dann auch UTF-8 sein, denn meine liebsten Editoren, wie Weaverslave können das nicht. Und was gibt es noch für Fallstricke bei einer Komplettumstellung?

                Tim

                1. echo $begrüßung;

                  Weil mich dieses Chaos nervt, denke ich jetzt darüber nach alles auf UTF-8 umzustellen, Ausgabeseiten, Mysql.
                  Aber macht das Sinn? oder kommt dann wieder irgendeine anderere Codierung die dann Hip ist?

                  Ja, das sehe (nicht nur) ich als sinnvoll an und vermutlich kommt auch langfristig gesehen keine andere Kodierung, weil Unicode so konzipiert ist, dass es im Prinzip unendlich erweiterbar ist. Auch die Transformationsvorschriften UTF-x bieten noch genügend Spielraum. Das UTF-8-Prinzip ist zwar (auf 4 Billionen Zeichen) begrenzt, doch denke ich nicht, dass das auf absehbare Zeit praktische Einschränkungen haben wird.

                  Muss zugeben, das mich das ganze Thema ein wenig überfordert, das war noch schön als man nicht drüber nachdenken musste und alles machte der Browser alleine.

                  Das machte er nicht, denn dazu mussten sich andere Leute den Kopf zerbrechen.

                  Vor allem macht mir ein Gedanke Kopfschmerzen, müssen die Scripte dann auch UTF-8 sein, denn meine liebsten Editoren, wie Weaverslave können das nicht. Und was gibt es noch für Fallstricke bei einer Komplettumstellung?

                  Das Thema ist nicht neu, das Archiv enthält bereits alle grundsätzlichen Informationen. Die beiden Grundprinzipien sind:

                  • Jedes beteiligtes System muss (für sich selbst betrachtet) mit der Kodierung zurecht kommen.
                  • An jedem Übergang zwischen zwei Systemen muss Klarheit über die verwendete Kodierung herrschen.

                  Alles andere sind Detailbetrachtungen. Zu erkennen, wo die Grenzen und Übergänge sind, ist manchmal etwas knifflig. Man benötigt das aber nicht nur wegen der Zeichenkodierungen sondern weil dabei auch immer ein Kontextwechsel stattfindet, der nicht unberücksichtigt bleiben darf. Jeder Kontext bringt ja weitere zu beachtenden Eigenheiten mit.

                  Wenn ein System nur Durchreicher eines Datenstroms ist, muss es möglicherwiese keine Ahnung von der Kodierung haben. PHP kann derzeit nicht (bzw. nur eingeschränkt) mit Mehrbytekodierungen umgehen. Wenn keine Stringverarbeitung (z.B. Trennen nach x Zeichen) vorgenommen werden soll, ist das nicht weiter tragisch. Vom DBMS abfragen und unbearbeitet an den Browser durchreichen geht problemlos, ebenso der umgekehrte Weg.

                  Solange keine Zeichen jenseits von ASCII direkt notiert werden müssen, ist auch eine Nicht-UTF-8-Fähigkeit eines Editors kein Hindernis. Ersatzdarstellungen (z.B. in Form von Hexwert-Notierungen) sind möglich aber unschön. Kontextfremde Ersatzdarstellungen sind hingegen zu vermeiden (HTML-Entitys und NCRs, wenn die HTML-Ausgabe noch lange nicht in Sicht ist). Das bringt nur weitere Probleme bei der nachfolgenden Verarbeitung.

                  Wie die einzelnen Systeme mit Zeichen(kodierungen) umgehen und was beim Übergang zwischen zwei Systemen zu beachten ist, sprengt den Rahmen einer kurzen Einleitung. Im Bedarfsfall bitte selbst recherchieren oder konkret nachfragen.

                  echo "$verabschiedung $name";

      2. echo $begrüßung;

        So nun zurück zu meinem Problem. Bedeutet das nun wenn es kein UTF-8 ist ist es automatisch iso bzw. kann ich falls FALSE unbesorgt utf8_encode anwenden?

        Nein, nur wenn Bytefolgen gefunden werden, die keine gültige UTF-8-Sequenz darstellen, kann man sagen, dass der Text kein UTF-8 ist. Es kann daraus keine Schlussfolgerung auf eine andere Kodierung getroffen werden, wenn du nicht den Möglichkeitsbereich auf einige wenige, eindeutig identifizierbare einschränken kannst. Mit dem "eindeutig identifizierbar" ist das aber so eine Sache, wie du aus

        http://forum.de.selfhtml.org/archiv/2008/9/t176846/#m1164170

        Svens Antwort und auch meinem kleinen theoretischem Beispiel sehen kannst. Das was du so lax als "iso" bezeichnet hast, ist eigentlich eine ganze Familie von Kodierungen (ISO-8859), die sich bei den Bedeutungen der Bytewerte zwischen 160 und 255 mehr oder wenige stark voneinander unterscheiden (siehe Tabelle auf der verlinkten Seite). Ohne eine inhaltliche Prüfung des Textes wirst du bei dem Bytewert 175 nicht entscheiden können, ob ein ¯, Ż, Џ, ―, Ŋ, ฏ, Æ oder Ÿ gemeint ist.

        Und dann gibt es neben der hierzulande üblichem ISO-8859-1 auch noch Windows-1252. Die Unterschiede liegen im Bereich 128 bis 159. Die Unterscheidung ist wichtig, denn manchmal werden (aus Unkenntnis) Windows-1252-Text als ISO-8859-1 deklariert. Die Browser sind da tolerant, aber einige Umkodierfunktionen sind penibel und wandeln ein 128er Windows-1252-€ nicht in das entsprechenden UTF-8-Pendant um, wenn ihnen erzählt wird, der Text sei ISO-8859-1. Und da haben sie vollkommen Recht.

        Aus praktischen Gesichtspunkten kannst du das Problem vielleicht wie folgt zufriedenstellend lösen: Erwartet werden nur ISO-8859-1, ISO-8859-15 und Windows-1252 nebst UTF-8. (Mit weiteren Kodierungen wird die Sache nicht einfacher.)

        • Sind in einem Text nur Bytes von 0 bis 127 zu finden, ist es ASCII. Die anderen genannten Kodierungen sind dann unwichtig, da ASCII in all diesen stets gleich ist.
        • Es ist (abgesehen von meinem Beispiel aus dem anderen Thread) relativ unwahrscheinlich, dass ein Text mit gültigen UTF-8-Sequenzen (also bei Zeichen jenseits von ASCII), etwas anderes als UTF-8 ist.
        • Ungültige UTF-8-Sequenzen sind also ISO-8859-1, 15 oder Windows-1252.
            - Kommen Bytes von 128 bis 159 vor, wird es Windows-1252 sein.
            - Die Wahrscheinlichkeit, dass mit Byte 164 das Währungszeichen ¤ gemeint ist, ist ziemlich gering.
              Es wird sich bei dem Text dann um ISO-8859-15 handeln.
            - Was jetzt noch übrig bleibt wird ISO-8859-1 sein.

        Übrig bleibt immer ein Rest Unsicherheit beziehungsweise eine Fehlerquote. (Dieser Rest ist die Differenz zwischen dem oben verwendeten "zufriedenstellend" und einem "100% fehlerfrei".) Kommen weitere Kodierungen hinzu, muss man diese ebenfalls in die Unterschiede-Suche (zwischen ihnen und den anderen kodierungen) und deren Wahrscheinlichkeitsbewertung einbeziehen.

        echo "$verabschiedung $name";

      3. Hi,

        Nun habe ich die Funktion valid_utf8() probiert, da bekomme ich dann tatsächlich 2 = false, 1= utf-8 "3". Wobei ich nicht ganz verstehe was mit den leveln 1-4 gemeint ist.

        Ein gültiges UTF-8-Zeichen kann aus 1 bis 4 Bytes bestehen. Wenn Du "3" als Ergebnis bekommst, ist mindestens ein Zeichen im Text, das aus 3 Bytes besteht, aber keines, das aus 4 Bytes besteht. Das ist soweit erstmal nicht wichtig. Besondere Beachtung kann man aber immer dem Ergebnis "1" schenken. Das bedeutet, daß der Text nicht nur gültiges UTF-8 ist, sondern auch gültiges ASCII (der Text ist also *u.a. auch* UTF-8, aber eben nicht nur).

        Gruß, Cybaer

        --
        Man muß viel gelernt haben, um über das, was man nicht weiß, fragen zu können.
        (Jean-Jacques Rousseau, Philosoph u. Schriftsteller)