Ankündigung

Einklappen
Keine Ankündigung bisher.

Zeichensatz in UTF-8 wandeln

Einklappen

Neue Werbung 2019

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

  • Zeichensatz in UTF-8 wandeln

    Hallo Zusammen

    Welche ist die zuverlässigste und sicherste Möglichkeit einen Datei-Inhalt in UTF-8 zu konvertieren.

    Ich kenne folgende 3 Varianten:
    - utf8_encode (konvertiert ISO-8859-1 in utf- -> nur ISO-8859-1
    - mb_convert_encoding -> vorraussetzung: PHP-Modul "MBstring" wurde geladen
    - iconv

    Welche Variante würdet ihr nutzen, wenn es sich um eine CSV-Datei handlet. Windows arbeitet ja im ASCII Format.
    ASCII sagt aber nicht viel über den Zeichensatz aus.
    Kann ich darauf gehen das ein Excell export im deutschsprachigen Raum immer "ISO-8859-1" zurückliefert.

    "ISO-8859-1" entspricht Latin-1 (Westeuropäisch)

    Danke im voraus!

  • #2
    Windows verwendet in Mitteleuropa CP 1252.

    Kommentar


    • #3
      Wenn die Daten aus Excel kommen, warum dann nicht gleich direkt die Excel-Datei lesen?

      Kommentar


      • #4
        Zitat von hellbringer Beitrag anzeigen
        Wenn die Daten aus Excel kommen, warum dann nicht gleich direkt die Excel-Datei lesen?
        Weil es zu Problemen führt zwischen den verschiedenen Excell Versionen. Hatte dieses Problem in der Vergangenheit. Man sollte generell auf CSV setzen und nicht auf das Excell Format. Ausser man möchte den Code alle 3 Jahre anpassen. Zudem kann man Daten aus einer Datenbank als CSV exportieren. So ist man als nicht an Excell gebunden.
        Trotzdem. Danke für deine Bemerkung.

        Kommentar


        • #5
          Beispiel:

          PHP-Code:
          //  config:
          echo 'config:' '<br/>';
          print_r(mb_detect_order());    //  Array ( [0] => ASCII [1] => UTF-8 )
          echo mb_internal_encoding();   //  ISO-8859-1
          echo '<br/><hr/>';

          //  code:
          $data = <<<EOT
            "aa;bbb;cc
            aa2;bb2;ccc2"
          EOT;

          $encoding getDetectedEncoding($data); //  ASCII

          if (!$encoding){
            echo 
          'Zeichensatz nicht vorhanden!';
          }
          else if (
          $encoding !== "UTF-8"){
            echo 
          $encoding '<br/>'//  ASCII
            
          $data mb_convert_encoding($data"UTF-8"$encoding);
            echo 
          'Daten wurden in UTF-8 gewandelt!<br/>'// eben nicht!

            //  immer noch ASCII
            
          echo getDetectedEncoding($data);
          }
          else {
            echo 
          'Daten sind schon in UTF-8 vorhanden!';
          }

          function 
          getDetectedEncoding ($res){
            return 
          mb_detect_encoding($resmb_list_encodings(), true);

          Kommentar


          • #6
            mb_detect_encoding() kannst du vergessen. Damit erkennst du in unserer Region den Unterschied zwischen UTF-Zeichensätzen und nicht UTF-Zeichensätzen. Damit ist es nicht möglich zu unterscheiden ob CP850, CP1252, ISO-8859-1, ISO-8859-15... die Zeichensätze sind dafür viel zu ähnlich und die Funktion viel zu "undeutsch". Um die zu unterscheiden oder besser gesagt zu erraten muss gezielt nach Umlauten, ß und € Symbol gesucht werden.

            Kommentar


            • #7
              Mal eine andere Frage:
              Macht es überhaupt Sinn den Zeichensatz zu untersuchen, respektive zu wandeln, wenn man aus der CSV-Datei ein JSON-file generieren möchte.
              In einer anderen Klasse möchte ich die JSON Daten in ein PHP Objekt wandeln.
              Ich machte schon die Erfahrung das nur "UTF-8 ohne BOM" reibungslos funktionierte. (z.B. bei json_decode)

              Kommentar


              • #8
                Na ja, früher oder später wirst du mit den Daten ja was machen wollen. Spätestens im neuen PHP-Objekt. Das heißt, du kommst so oder so nicht drum herum, den Zeichensatz kennen zu müssen.

                Kommentar


                • #9
                  Mal angenommen das zu erstellende JSON-Objekt wäre simple.
                  Ohne die Überprüfung und Konvertierung des Zeichensatzes in UTF-8 gibt es probleme, falls ich später die json-Daten einlese und in ein PHP Objekt wandle.
                  PHP-Code:
                  //1. csv to array
                  $csvArray array_map(functiom($row){.........}, str_getcsv($fileContentPHP_EOL));

                  //2. convert array to json. store json data
                  file_put_contents("data.json" ,json_encode($csvArray)); 
                  Für dieses Problem gibt es sicher eine Lösung.

                  Kommentar


                  • #10
                    Du könntest alle Strings mit Base64 kodieren, bevor du json_encode aufrufst, und sie nach dem Aufruf von json_decode wieder dekodieren. Das verschiebt dein Problem, den korrekten Zeichensatz wissen zu müssen, aber vermutlich nur.

                    Vielleicht kannst du die Strings auch als Binärdaten auffassen und irgendwie in diese \u-Kodierung überführen. Das wäre vermutlich eleganter, aber müsste ich jetzt auch erst nachforschen. (Edit: Ne, ich glaube, das ergibt keinen Sinn.) (Edit: Und wäre wenn natürlich auch nur eine Verschiebung des eigentlichen Problems.)

                    Kommentar


                    • #11
                      JSON eignet sich nicht für Binärdaten. Dafür gibt es BSON. Aber ich denke hier verrennt man sich nur in neue Problem. CSV eignet sich nun mal nicht wirklich für einen universellen Datenaustausch, sondern funktioniert nur unter bestimmten Rahmenbedinungen (wie zB., dass eben die Zeichenkodierung bekannt sein muss). Deswegen auch mein Vorschlag mit Excel-Dateien, weil es hier diese Problematik nicht gibt.

                      Ich habe schon jahrelang Excel-Importe und -Exporte programmiert und noch nie Versionsprobleme oder ähnliches gehabt. Kann also die Sorgen nicht nachvollziehen, und die Entscheidung so ein verwaschenes und undefiniertes Datenformat wie CSV zu verwenden schon gar nicht.

                      Kommentar


                      • #12
                        Zitat von hellbringer Beitrag anzeigen
                        Kann also die Sorgen nicht nachvollziehen, und die Entscheidung so ein verwaschenes und undefiniertes Datenformat wie CSV zu verwenden schon gar nicht.
                        CSV ist kein verwaschenes und undefiniertes Datenformat ! Jede Datenbank bietet einen CSV Import oder Export an. Die PHP-core selber hat CSV funktionen.
                        Worauf man halt achten muss sind die Delimiter.
                        Ich bin hier anderer Meinung.

                        Lösungsweg:
                        Ich grenze den möglichen, zu erwartenden Zeichensatz wie folgt ein. (westeuropäischer Zeichensatz: ISO-8859-1 auch bekannt als Latin-1 und WINDOWS-1252)
                        PHP-Code:
                        $detectedEncoding mb_detect_encoding($fileContent'UTF-8, ISO-8859-1, WINDOWS-1252'true);
                          If (
                        $detectedEncoding) {
                            if (
                        $detectedEncoding !== 'UTF-8') {
                              
                        $fileContent iconv($detectedEncoding'UTF-8'$fileContent);
                            }

                        Kommentar


                        • #13
                          CSV ist kein verwaschenes und undefiniertes Datenformat ! Jede Datenbank bietet einen CSV Import oder Export an. Die PHP-core selber hat CSV funktionen.
                          Doch, ist es leider. Das fängt – wie du schon sagst – damit an, dass es Anwendungen zulassen, verschiedene Delimiter und Feldbegrenzer und dergleichen zu generieren. Diese Daten kannst du nur dann wieder einlesen, wenn du die genauen Delimiter und so kennst. Das ist für ein Datenaustauschformat ziemlich absurd.

                          Es gibt zwar ein RFC, aber an das hält sich niemand. Insbesondere nicht PHP.

                          - https://bugs.php.net/bug.php?id=50686
                          - https://bugs.php.net/bug.php?id=43225

                          Kommentar


                          • #14
                            Zitat von antic_schweiz Beitrag anzeigen
                            CSV ist kein verwaschenes und undefiniertes Datenformat !
                            Ein allgemeiner Standard für das Dateiformat CSV existiert nicht, jedoch wird es im RFC 4180 grundlegend beschrieben. Die zu verwendende Zeichenkodierung ist ebenso wenig festgelegt; 7-Bit-ASCII-Code gilt weithin als der kleinste gemeinsame Nenner.

                            https://de.wikipedia.org/wiki/CSV_%28Dateiformat%29

                            Zitat von antic_schweiz Beitrag anzeigen
                            Ich grenze den möglichen, zu erwartenden Zeichensatz wie folgt ein. (westeuropäischer Zeichensatz: ISO-8859-1 auch bekannt als Latin-1 und WINDOWS-1252)
                            ISO-8859-1, Latin-1 und Windows-1252 sind unterschiedliche Kodierungen. Sie sind zwar recht ähnlich, aber es gibt trotzdem Unterschiede.

                            Kommentar


                            • #15
                              Zitat von antic_schweiz Beitrag anzeigen

                              Lösungsweg:
                              Ich grenze den möglichen, zu erwartenden Zeichensatz wie folgt ein. (westeuropäischer Zeichensatz: ISO-8859-1 auch bekannt als Latin-1 und WINDOWS-1252)
                              PHP-Code:
                              $detectedEncoding mb_detect_encoding($fileContent'UTF-8, ISO-8859-1, WINDOWS-1252'true);
                              If (
                              $detectedEncoding) {
                              if (
                              $detectedEncoding !== 'UTF-8') {
                              $fileContent iconv($detectedEncoding'UTF-8'$fileContent);
                              }

                              Das funktioniert nicht. Erstelle mal per Excel CSV-Dateien, welche
                              1. Nur ASCII Zeichen
                              2. ASCII und Umlaute öäüß
                              3. ASCII und das €
                              enthalten und schau dir deine Ergebnisse mit mb_detect_encoding an. Bei mir wird da WINDOWS-1252 gar nicht erkannt. erc hat das in #3 schon auf den Punkt gebracht.
                              Nimmst du einfach ISO-8859-1, dann wird das € z.B. nicht erkannt.
                              Wenn möglich, solltest du die Herkunft (und damit den Zeichensatz) kennen und setzen. Mit einer Erweiterungsklasse zum SplFileObject sieht das dann so aus:
                              PHP-Code:
                              $json CsvFileObject::create($csvFileName)
                                ->
                              setInputCharSet("CP1252")
                                ->
                              toJSON(); 
                              Für CSV-Dateien aus Excel (Win) setze ich CP1252 fest für den Input und nutze intern iconv().

                              Kommentar

                              Lädt...
                              X