WernerK: mb_detect_encoding?

Hallo,

ein PHP script liest eine CSV Datei ein die in Ascii ist und auch Umlaute enthalten kann.
Die PHP Seite liefert in UTF-8 aus. (<meta charset="utf-8">)

Umlaute in der CSV werden daher so angezeigt:

�berregional

Ich wollte nun mit "mb_detect_encoding" herausfinden wie die Kodierung des Strings ist.

  
$charset =  mb_detect_encoding($teststring,"UTF-8, ASCII, ISO-8859-1, ISO-8859-15",true);  
echo "der Test $teststring hat charset $charset <br>";  

Was micht nun etwas verwirrt ist die Ausgabe:

Wenn String = "gelb"
der Test gelb hat charset UTF-8

Bei "grün"
der Test gr�n hat charset ISO-8859-1

Ich hatte das gerade anders herum erwartet.
Oder habe ich da was falsch verstanden?

Gruss
Werner

  1. Hi,

    Ich wollte nun mit "mb_detect_encoding" herausfinden wie die Kodierung des Strings ist.

    Das läßt sich nicht immer zweifelsfrei bestimmen, sondern oftmals nur an Hand von Indizien mehr oder weniger gut „erraten“.

    Wenn String = "gelb"
    der Test gelb hat charset UTF-8

    Bei "grün"
    der Test gr�n hat charset ISO-8859-1

    Ich hatte das gerade anders herum erwartet.

    Der ASCII-Zeichenbereich wird in UTF-8 ganz genauso kodiert wie in ASCII.

    g, e, l, b sind alles Zeichen, die ASCII enthält. Deshalb ist das auch gleichzeitig gültiges UTF-8. Diesen String „als UTF-8“ weiter zu be- und verarbeiten ist also problemlos möglich.

    In deinem „grün“ ist aber das ü aber als ISO-8859-1 kodiert, das sich an der Stelle nicht mit UTF-8 deckt.

    MfG ChrisB

    --
    Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
    1. Hallo,

      Das läßt sich nicht immer zweifelsfrei bestimmen, sondern oftmals nur an Hand von Indizien mehr oder weniger gut „erraten“.

      was würde sich denn dann anbieten wenn das nicht zuverlässig arbeitet?

      Vorrausgesetzt die CSV Datei liegt immer in Ascii vor und enthält Umlaute.
      Könnte man dann nicht einfach generell mit utf8_encode() alles Strings umwandeln?

      $tmp = utf8_encode($teststring);

      Gruss
      Werner

      1. Hi,

        Vorrausgesetzt die CSV Datei liegt immer in Ascii vor und enthält Umlaute.

        Das ist überhaupt nicht möglich, weil ASCII die deutschen Umlaute nicht abbildet.

        MfG ChrisB

        --
        Autocomplete has spoiled me to a point where it happens every so often that I encounter a CAPTCHA, and I just type in the first character … and then wait for the rest of the code to be automatically suggested :/
        1. Das ist überhaupt nicht möglich, weil ASCII die deutschen Umlaute nicht abbildet.

          sorry, Ich meint ANSI. Mein Editor zeigt die CSV Datei als Ansi Kodierung an.

          Gruss
          Werner

          1. @@WernerK:

            nuqneH

            sorry, Ich meint ANSI. Mein Editor zeigt die CSV Datei als Ansi Kodierung an.

            Du meinst vermutlich ISO 8859-1, egal wie dein Editor das nennt.

            Qapla'

            --
            „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
  2. @@WernerK:

    nuqneH

    $charset = mb_detect_encoding($teststring,"UTF-8, ASCII, ISO-8859-1, ISO-8859-15",true);

    Wenn ich die nicht allzu geschwätzige Doku richtig verstehe, prüft mb_detect_encoding() die Liste der Codierungen durch, welche davon als erste zu der Bytesequenz $teststring passt.

    Da jede gültige ASCII-Bytesequenz (d.h. nur Werte bis x0F) auch eine gültige UTF-8-Bytesequenz ist, macht die Angabe ASCII hinter UTF-8 keinen Sinn. (Bytesequenzen mit ausschließlich Werten bis x0F wurden bereits als UTF-8 erkannt.)

    Auch hat die Funktion keine Chance zu erkennen, ob die vorliegende Bytesequenz nun ISO 8859-1 oder ISO 8859-15 ist. (Soll der Bytewert xBD für ½ oder für œ stehen?)

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
    1. Hallo

      Da jede gültige ASCII-Bytesequenz (d.h. nur Werte bis x0F) auch eine gültige UTF-8-Bytesequenz ist, macht die Angabe ASCII hinter UTF-8 keinen Sinn. (Bytesequenzen mit ausschließlich Werten bis x0F wurden bereits als UTF-8 erkannt.)

      Auch hat die Funktion keine Chance zu erkennen, ob die vorliegende Bytesequenz nun ISO 8859-1 oder ISO 8859-15 ist. (Soll der Bytewert xBD für ½ oder für œ stehen?)

      Danke für den Hinweis. Das bedeutet es reicht diese Angabe?

      mb_detect_encoding($teststring,"UTF-8, ISO-8859-1",true);

      Gruss
      Werner

  3. Hi,

    ein PHP script liest eine CSV Datei ein die in Ascii ist und auch Umlaute enthalten kann.

    das ist ein Widerspruch; ASCII enthält keine Umlaute.

    Umlaute in der CSV werden daher so angezeigt:
    �berregional

    Das scheint dann wohl eher irgendeine 1-Byte-ISO-Codierung zu sein, etwa ISO-8859-x, vielleicht auch Windows-1252 oder sowas.

    Ich wollte nun mit "mb_detect_encoding" herausfinden wie die Kodierung des Strings ist.

    Das ist nicht wirklich zuverlässig möglich.

    Wenn String = "gelb"
    der Test gelb hat charset UTF-8

    Dieser Beispieltext enthält nur ASCII-Zeichen. ASCII ist aber sowohl eine Untermenge von UTF-8 als auch ISO-8859-1, also wären alle drei Angaben richtig, weil nicht unterscheidbar.

    Bei "grün"
    der Test gr�n hat charset ISO-8859-1

    Basierend auf Mutmaßung, ja.

    Ich hatte das gerade anders herum erwartet.

    Warum?

    Ciao,
     Martin

    --
    Du kannst dem Leben nicht mehr Tage geben.
    Aber dem Tag mehr Leben.
    Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
    1. Hallo,

      das ist ein Widerspruch; ASCII enthält keine Umlaute.

      Wie ich schon geschrieben hatte, meinte ich ISO-8859-1 und nicht Ascii.
      Wenn also mb_detect_encoding nicht zuverlässig ist (so wie es auch im Manual ganz unten erwähnt wird), was kann man dann tun?

      Wie gesagt: Wenn die CSV IMMER in ISO-8859-1 vorliegen würde, könnte man ja vermutlich alle Strings mit utf8_encode() umwandeln oder?

      Es gäbe nur ein Problem wenn die Datei schon utf8 kodiert wäre.

      Wie würdest du vorgehen?

      Gruss
      Werner

      1. Hi,

        Wenn also mb_detect_encoding nicht zuverlässig ist (so wie es auch im Manual ganz unten erwähnt wird), was kann man dann tun?

        Anhand einer Bytefolge kann nicht zuverlässig ermittelt werden, in welcher Codierung diese vorliegt. Egal welches Tool benutzt wird.

        Es können nur anhand von einzelnen Bytes oder auch Bytefolgen verschiedene Codierungen ausgeschlossen werden - nämlich dann, wenn diese Bytes oder Bytefolgen in der jeweiligen Codierung nicht vorkommen dürfen.

        Hast Du z.B. ein Byte mit Wert größer 128, kann ASCII ausgeschlossen werden.
        Wenn Du aber nur Werte kleiner als 128 hast, kannst Du nicht wissen, ob das ASCII, UTF-8, ISO-8859-x oder EBCDIC ist.

        cu,
        Andreas

        --
        Warum nennt sich Andreas hier MudGuard?
        O o ostern ...
        Fachfragen per Mail sind frech, werden ignoriert. Das Forum existiert.
      2. Hi,

        Wie würdest du vorgehen?

        ich würde mich beim Ersteller der CSV-Datei nach deren Spezifikation (Codierung) erkundigen, und ihn darauf festnageln, dass er sich dann auch konsequent an die Angabe hält.

        Ciao,
         Martin

        --
        Wenn der Computer wirklich alles kann,
        dann kann er mich mal kreuzweise.
        Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        1. Moin Martin,

          Wie würdest du vorgehen?

          ich würde mich beim Ersteller der CSV-Datei nach deren Spezifikation (Codierung) erkundigen, und ihn darauf festnageln, dass er sich dann auch konsequent an die Angabe hält.

          Das geht nur, wenn das Zielpublikum entweder technisch versiert ist oder wenn man den Anwender schulen kann. Wenn du einem nicht technisch versierten Menschen mit dem Wort „Kodierung“ kommst, dann schaut er dich nur ratlos an.

          Nein, ich würde prüfen, ob es gültiges UTF-8 ist. Falls ja, würde ich UTF-8 annehmen, ansonsten ISO-8859-15. Damit erschlägt man den überwiegenden Grossteil der Anwendungsfälle.

          LG,
           CK

          1. Hallo,

            Nein, ich würde prüfen, ob es gültiges UTF-8 ist. Falls ja, würde ich UTF-8 annehmen, ansonsten ISO-8859-15. Damit erschlägt man den überwiegenden Grossteil der Anwendungsfälle.

            und wie würdest du das dann prüfen?
            Eben mit mb_detect_encoding() oder mit anderen Funktionen?

            Gruss
            Werner

            1. Moin WernerK,

              Nein, ich würde prüfen, ob es gültiges UTF-8 ist. Falls ja, würde ich UTF-8 annehmen, ansonsten ISO-8859-15. Damit erschlägt man den überwiegenden Grossteil der Anwendungsfälle.

              und wie würdest du das dann prüfen?
              Eben mit mb_detect_encoding() oder mit anderen Funktionen?

              Genau das ist es, was mb\_detect\_encoding() tut, ich würde diese Funktion nutzen, ja.

              LG,
               CK

          2. Hallo,

            ich würde mich beim Ersteller der CSV-Datei nach deren Spezifikation (Codierung) erkundigen, und ihn darauf festnageln, dass er sich dann auch konsequent an die Angabe hält.
            Das geht nur, wenn das Zielpublikum entweder technisch versiert ist

            ja, genau davon bin ich stillschweigend ausgegangen. Ich dachte, wer verarbeitbare, einigermaßen korrekte CSV-Dateien erzeugt, wird wohl einen Wissensstand haben, bei dem man das erwarten darf.

            Aber du hast natürlich recht, dazu hat Werner nichts gesagt; es könnte also auch ein angelernter Laie sein. Doch selbst dann kann man ihm dabei assistieren, die Einstellungen seiner Software einmal passend vorzunehmen und ihn dann bitten, diese Einstellungen nicht zu verändern.

            Wenn du einem nicht technisch versierten Menschen mit dem Wort „Kodierung“ kommst, dann schaut er dich nur ratlos an.

            Ja, vor allem mit 'K'. ;-)
            Im Ernst: Natürlich muss man den Leuten das so erklären, dass sie es mit ihrem Wissensstand auch erfassen können. Und dabei nicht weiter als nötig ins Detail gehen. Es sei denn, der/diejenige lässt echtes Interesse erkennen und fragt konkret nach.

            Nein, ich würde prüfen, ob es gültiges UTF-8 ist. Falls ja, würde ich UTF-8 annehmen, ansonsten ISO-8859-15. Damit erschlägt man den überwiegenden Grossteil der Anwendungsfälle.

            Das ist vermutlich wahr. Keine schulmäßige, aber eine pragmatische Lösung.

            Ciao,
             Martin

            --
            Drei Sachen vergesse ich immer wieder: Telefonnummern, Geburtstage und ... äääh ...
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            1. Moin Martin,

              ich würde mich beim Ersteller der CSV-Datei nach deren Spezifikation (Codierung) erkundigen, und ihn darauf festnageln, dass er sich dann auch konsequent an die Angabe hält.
              Das geht nur, wenn das Zielpublikum entweder technisch versiert ist

              ja, genau davon bin ich stillschweigend ausgegangen. Ich dachte, wer verarbeitbare, einigermaßen korrekte CSV-Dateien erzeugt, wird wohl einen Wissensstand haben, bei dem man das erwarten darf.

              Naja, ich kann dir erklären, wie das bei einem unserer Kunden läuft: da geht der Büroleiter am Ende des Tages hin, exportiert eine Excel-Tabelle nach CSV und importiert sie dann in einem Web-Formular. Der kann zwar in Excel-Tabellen eintragen, aber schon der Begriff CSV ist für ihn eine Blackbox ;)

              Aber du hast natürlich recht, dazu hat Werner nichts gesagt; es könnte also auch ein angelernter Laie sein. Doch selbst dann kann man ihm dabei assistieren, die Einstellungen seiner Software einmal passend vorzunehmen und ihn dann bitten, diese Einstellungen nicht zu verändern.

              Erfahrungsgemäss geht das eine Zeit lang gut (etwa bis $mitarbeiter im Urlaub ist) und danach gehts kaputt.

              Wenn du einem nicht technisch versierten Menschen mit dem Wort „Kodierung“ kommst, dann schaut er dich nur ratlos an.

              Ja, vor allem mit 'K'. ;-)

              Diese Schreibweise ist übrigens korrekt, Kodierung ist eine alternative Schreibweise zu Codierung :/

              Im Ernst: Natürlich muss man den Leuten das so erklären, dass sie es mit ihrem Wissensstand auch erfassen können. Und dabei nicht weiter als nötig ins Detail gehen. Es sei denn, der/diejenige lässt echtes Interesse erkennen und fragt konkret nach.

              klar kann man versuchen das zu erklären, aber meine Erfahrung im Büroalltag sagt: das wird nicht zum gewünschten Effekt führen.

              LG,
               CK

              1. Hi,

                Wenn du einem nicht technisch versierten Menschen mit dem Wort „Kodierung“ kommst, dann schaut er dich nur ratlos an.
                Ja, vor allem mit 'K'. ;-)
                Diese Schreibweise ist übrigens korrekt, Kodierung ist eine alternative Schreibweise zu Codierung :/

                ja, ich weiß, aber für mein Empfinden sieht das irgendwie "kaputt" aus. Fast so schlimm wie Frisör anstatt Friseur.

                klar kann man versuchen das zu erklären, aber meine Erfahrung im Büroalltag sagt: das wird nicht zum gewünschten Effekt führen.

                Mag sein; kommt auf die Zielgruppe an. Aber ich habe auch meist eher mit technophilen Menschen zu tun.

                Ciao,
                 Martin

                --
                Treffen sich zwei Freundinnen nach langer Zeit wieder. "Gut siehste aus. Hast du abgenommen?" - "Nö." - "Hmm, dann haste zugenommen. Steht dir aber gut."
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                1. Tach!

                  klar kann man versuchen das zu erklären, aber meine Erfahrung im Büroalltag sagt: das wird nicht zum gewünschten Effekt führen.
                  Mag sein; kommt auf die Zielgruppe an. Aber ich habe auch meist eher mit technophilen Menschen zu tun.

                  Ich kann dir versichern, dass Sprüche wie der nachfolgende nicht bar jeder Grundlage sind:

                  "Manchmal komme ich mir vor, wie in einem Asterix-Comic. Umzingelt von den Kollegen Denktnix, Machtnix, Weissnix und Kannix...
                  Und das Schlimmste ist, ich gehöre auch bald dazu, als Erklärnix, weil das Bringtnix!"

                  dedlfix.

        2. @@Der Martin:

          nuqneH

          ich würde mich beim Ersteller der CSV-Datei nach deren Spezifikation (Codierung) erkundigen, und ihn darauf festnageln, dass er sich dann auch konsequent an die Angabe hält.

          Dann eher darauf festnageln, dass er konsequent UTF-8 verwendet. Und das auch so in der Spezifikation festschreiben.

          Qapla'

          --
          „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
          1. ich würde mich beim Ersteller der CSV-Datei nach deren Spezifikation (Codierung) erkundigen, und ihn darauf festnageln, dass er sich dann auch konsequent an die Angabe hält.

            Dann eher darauf festnageln, dass er konsequent UTF-8 verwendet. Und das auch so in der Spezifikation festschreiben.

            Womit Du -erneut- Deine umfassende Projekterfahrung im Endkundengeschäft darlegst. Nichts für ungut, aber der musste bei der (für mich augenblicklichen!) Gelegenheit mal raus.

            1. Womit Du -erneut- Deine umfassende Projekterfahrung im Endkundengeschäft darlegst. Nichts für ungut, aber der musste bei der (für mich augenblicklichen!) Gelegenheit mal raus.

              Das ist recht. Wenn ich "Pizza fastix" haben will und zahlen soll, dann will ich, darauf Birne und keine Ananas ist. Sonst wäre es ja "Hawai". Allerdings darf ich dann nicht verlangen, dass Kirschen unter dem Käse sind. Dann hätte ich Pizza "Tokyo" verlangen müssen.

              Die nächste Frage ist, ob es denn der Kunde ist, der die Daten liefert. Die können ja automatisch erstellt werden.

              z.B. wird etwas wie ein

              $sh='export LANG="de_DE.UTF-8"; whois ' . escapeshellarg($domain);  
              $txt=`$sh`;
              

              trotz korrekt gesetzter Umgebungsvariable die Ausgaben zwar zurück liefern, aber die Kodierung bleibt völlig willkürlich. Denn die bestimmt der  Betreiber des whois Servers (bzw. der Registrator) - und zwar ohne die zu erwähnen! Man mache mal ein whois auf IP's von Telefonica um sich zu überzeugen...

              In solchen Fäll wirkt, trotz aller Unsicherheiten, die Spekulation mit mb_detect_encoding recht nützlich:

              $coding = mb_detect_encoding($txt, 'ASCII, 'Windows-1252', 'ISO-8859-15', 'UTF-8'); # eventuell erweitern...  
              if ( ! 'UTF-8' == $coding ) { $txt=iconv($coding, 'UTF-8', $txt); }  
              
              

              Leben, Frau, Gesundheit würde ich dem allerdings nicht anvertrauen....

              Jörg Reinholz

              1. Tach!

                In solchen Fäll wirkt, trotz aller Unsicherheiten, die Spekulation mit mb_detect_encoding recht nützlich:

                $coding = mb_detect_encoding($txt, 'ASCII, 'Windows-1252', 'ISO-8859-15', 'UTF-8'); # eventuell erweitern...

                if ( ! 'UTF-8' == $coding ) { $txt=iconv($coding, 'UTF-8', $txt); }

                
                > Leben, Frau, Gesundheit würde ich dem allerdings nicht anvertrauen....  
                  
                Vor allem (mal abgesehen von der falschen Syntax) nicht bei dieser Reihenfolge der Kodierungen.  
                  
                ASCII wird als Ergebnis ausgegeben, wenn kein Wert > 0x7F im Test-String enthalten ist. Soweit so richtig. Jetzt muss aber UTF-8 kommen, denn alle UTF-8-Sequenzen sind auch gültiges Windows-1252 oder ISO-8859-irgendwas. Wenn diese Ein-Byte-Kodierungen vor den Mehrbyte-Kodierungen stehen, werden sie in den meisten Fällen als gültig erkannt und als Ergebnis zurückgeliefert.  
                  
                ~~~php
                var_dump(mb_detect_encoding("ä", 'ascii,iso-8859-1,utf-8'));  
                var_dump(mb_detect_encoding("ä", 'ascii,utf-8,iso-8859-1'));
                

                Unter der Voraussetzung, dass das 'ä' UTF-8-kodiert ist, ist der Ergebnis der beiden Zeilen ISO-8859-1 und UTF-8. UTF-8 muss den ISOs stehen, damit es erkannt werden kann.

                In ISO-8859-1 ist der Bereich \x7F bis \x9F undefiniert, mit keinen Zeichen belegt. Siehe dazu Wikipedia ISO-8859-1. Es gibt eine Variante, in der diese Lücke mit Steuerzeichen gefüllt ist. Auf alle Fälle ist aber in Windows-1252 dieser Bereich mit "richtigen Zeichen" gefüllt.

                var_dump(mb_detect_encoding("\x83", 'windows-1252,iso-8859-1'));  
                var_dump(mb_detect_encoding("\x83", 'iso-8859-1,windows-1252'));
                

                mb_detect_encoding() ist aber nicht in der Lage, da Unterschiede zu sehen. Es ist also völlig egal, in welcher Reihenfolge man diese beiden Kodierungen angibt, die erste gewinnt immer. Bei Ein-Byte-Kodierungen kann weder diese Funktion die richtige Kodierung erkennen, noch irgendein anderer Mechanismus, der keine Inhaltsanalyse auf Plausibilität des Textes vornimmt. Google kann sowas, die haben aber auch einen riesigen Datenbestand, den sie zurate ziehen können.

                Dass die Reihenfolge der zu testenden Kodierungen relevant ist, war in diesem Thread eigentlich bereits geklärt. Man muss es nochmal mit aller Deutlichkeit sagen: Diese Funktion gibt allein anhand der Gültigkeit der Bytesequenzen das erstbeste passende Kodierungsangabe zurück. Und zwar völlig unabhängig davon, ob der Text derart dekodiert den urspünglichen Text ergibt oder nicht. Um beim Wetten um "Leben, Frau und Gesundheit" überhaupt eine realistische Chance auf den Gewinn zu haben, muss man sich schon mit Kodierungen und den technischen (Un)Möglichkeiten ihrer Erkennung vertraut gemacht haben.

                Generell kann man sagen, dass eine Dekodierung von beliebigen Daten - sei es Text oder "richtig" verschlüsselte Daten - unmöglich ist, wenn man nicht weiß, welche Kodierungsvorschrift verwendet wurde. Das ist schließlich das Grundprinzip einer Kodierung. Es gibt zwar diverse Vorgehensweisen, um an die ursprünglichen Daten zu kommen, aber keine davon kann eine 100%-Erfolgsgarantie geben, auch wenn man mit der einen oder anderen eine ausreichende Genauigkeit für den einen oder anderen Anwendungsfall erzielen kann.

                dedlfix.

                1. Vor allem (mal abgesehen von der falschen Syntax) nicht bei dieser Reihenfolge der Kodierungen.

                  Stimmt. Der heiße Test ergab, mit

                    $spek=array('ASCII', 'UTF-8', 'ISO-8859-1');  
                    $coding = mb_detect_encoding($s, $spek, false); # eventuell erweitern...  
                    if ( 'UTF-8' != $coding && 'ASCII' != $coding ) {  
                      $s = "(Original vermutlich $coding - kodiert)" . mb_convert_encoding($s, 'UTF-8', $coding);  
                    }
                  

                  Tut es erst mal, was es soll - aber Leben, Frau, Gesundheit würde ich dem allerdings nicht anvertrauen....

                  Jörg Reinholz

  4. Hallo,

    Ich wollte nun mit "mb_detect_encoding" herausfinden wie die Kodierung des Strings ist.

    Du wirst damit leben müssen, dass es nicht zuverlässig möglich ist, anhand von Bytesequenzen festzustellen, welche Zeichenkodierung vorliegt. Weder mit PHP noch mit irgendwelchen anderen Programmiersprachen.

    MfG