KampfHitsKeks: Csv Datei zeilenweise auslesen als Array zurück geben

Hallo, wie meine Überschrift bereits mein Problem beschreibt bekomme ich die Daten nicht vernünftig auslesen.Zumindest müsste ich Daten die wie folgt aufgebaut sind:

dt_Jahr   dt_Nummer     dt_Kilometer
01022008  15795464      4564km
.
.
.

Diese Daten sollten dann zeilenweise ausgelesen werden, und als Array zurückgegeben werden leider raffe ich das nicht so ganz.
wäre schön wenn mir wer weiterhelfen könnte. Hier der aktuelle Codeschnippsel.(Die Ausgabe soll als wiederkehrende Funktion auftauchen da dies öfter verwendet wird)

function holeDaten($filename, &$_buffer, $maxrecsize=2048) ##function öffnen  
   {  
  
   $fh = fopen($filename,'r');  
   $_rec = array();  
       while ($false !==($rec = fgetcsv($fh, $maxrecsize, ';', '"'))  
       {  
         $_buffer[] = $_rec;  
       }  
       fclose($fh);  
       return 0;  
   }  
  
 $_buffer = array();  
    $err_hd = holeDaten('xxx.csv',$_buffer);  
    if ($err_hd == 0)  
    {  
        echo "<pre>\r\n";  
        echo print_r($_buffer,1);  
        echo "</pre>\r\n";  
    }  
    else  
    {  
        echo "<p>Fehler beim Lesen von ".$filename.": $err_hd <p>\r\n";  
    }

MfG
KampfHitsKeks

  1. Hello,

    da erkenne ich doch meinen Code :-)
    Ist aber ein fehler drin.
    Zum Debuggen bitte immer im Script oder im Verzeichnis

    Error_Reporting(E_ALL);

    benutzten.

    function holeDaten($filename, &$_buffer, $maxrecsize=2048) ##function öffnen

    {

    $fh = fopen($filename,'r');
       $_rec = array();

    while ($false !==($_rec = fgetcsv($fh, $maxrecsize, ';', '"'))
    #                           ^

    {
             $_buffer[] = $_rec;
           }
           fclose($fh);
           return 0;
       }

    $_buffer = array();
        $err_hd = holeDaten('xxx.csv',$_buffer);
        if ($err_hd == 0)
        {
            echo "<pre>\r\n";

    echo htmlspecialchars(print_r($_buffer,1));

    echo "</pre>\r\n";
        }
        else
        {
            echo "<p>Fehler beim Lesen von ".$filename.": $err_hd <p>\r\n";
        }

      
      
    Schau mal, ob es so funktioniert.  
      
      
      
    Liebe Grüße aus Syburg  
      
    Tom vom Berg  
    ![](http://selfhtml.bitworks.de/Virencheck.gif)  
      
    
    -- 
    Nur selber lernen macht schlau  
    <http://bergpost.annerschbarrich.de>
    
    1. Leider bekomme ich wenn ich Error_Reporting(E_ALL); benutze keine Ausgabe.

      1. Hello,

        Leider bekomme ich wenn ich Error_Reporting(E_ALL); benutze keine Ausgabe.

        Wie? Gar keine Ausgabe?

        Liebe Grüße aus Syburg

        Tom vom Berg

        --
        Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
        1. Hello,
          »»
          »» Leider bekomme ich wenn ich Error_Reporting(E_ALL); benutze keine Ausgabe.

          Wie? Gar keine Ausgabe?

          Liebe Grüße aus Syburg

          Tom vom Berg

          Nein, die Seite bleibt komplett weiß. Problem ist wenn ich den kleinen Teil von Joachim benutze kann ich dies nicht weiterverwenden (die Funktion soll später eine Tabelle bilden) und von daher brauch ich das einzelne Auslesen dieser Daten.

          1. Hello,

            »» Leider bekomme ich wenn ich Error_Reporting(E_ALL); benutze keine Ausgabe.

            Wie? Gar keine Ausgabe?

            Nein, die Seite bleibt komplett weiß. Problem ist wenn ich den kleinen Teil von Joachim benutze kann ich dies nicht weiterverwenden (die Funktion soll später eine Tabelle bilden) und von daher brauch ich das einzelne Auslesen dieser Daten.

            Wo hast Du denn den Codeschnipsel gefunden? Das war sicherlich nur eine Skizze, oder er sit nicht vollständig.

            Anschließend das korrigierte und _ausgetestete_ Script:

            <?php   ### getcsv.php ###

            error_reporting(E_ALL);
            ini_set('display_errors', 1);

            #------------------------------------------------------------------------------
            function holeDaten($filename, &$_buffer, $maxrecsize=2048) ##function öffnen
            {
               $fh = fopen($filename,'r');
               if (!$fh) { return 2; }       ## Fehlercode 2 für "kann nicht öffnen" zurückgeben
               if (!flock($fh, LOCK_SH))
               {
                   flcose($fh);
                   return 5;                ## Fehlercode 5 für "kann nicht sperren" zurückgeben
               }

            $_rec = array();

            while (false !==($_rec = fgetcsv($fh, $maxrecsize, ';', '"')))
               {
                   $_buffer[] = $_rec;
               }
               fclose($fh);
               return 0;
            }

            #==============================================================================

            php main

            #==============================================================================

            $_buffer = array();

            $err_hd = holeDaten('xxx.csv',$_buffer);

            if ($err_hd == 0)
             {
                 echo "<pre>\r\n";
                 echo htmlspecialchars(print_r($_buffer,1));
                 echo "</pre>\r\n";
             }
             else
             {
                 echo "<p>Fehler beim Lesen von ".$filename.": $err_hd <p>\r\n";
             }
            ?>

            und hier ein paar Musterdaten (einfach mit Copy & Paste in eine ASCII-Datei xxx.csv schieben:

            1234;2348;1388
            ;;;"Hallo";"Thomas"

            "CSV-Test";"falsche Zeilenlänge";9999;1355
            "Text mit
            Umbruch und sonstigen ""Schweinereien"";";88888;"Ende"

            Das Auffüllen auf eine canonische Tabelle musst Du bei CSV noch selber erledigen. Dazu musst Du aber  ersteinmal wissen, welche Zeile die meisten Elemente hat, damit du die anderen Zeilen mite leeren Array-Elementen auffülen kannst und ggf. leere Zeilen entfernen kannst.

            Das könnte man der Funktion hole_daten() auch noch beibringen.

            Liebe Grüße aus Syburg

            Tom vom Berg

            --
            Nur selber lernen macht schlau
            http://bergpost.annerschbarrich.de
            1. »»Wo hast Du denn den Codeschnipsel gefunden? Das war sicherlich nur eine Skizze, oder er sit nicht vollständig.

              Den Codeschnipsel hatte ich auch hier im Forum gefunden, hatte mich schon ein bisschen umgekuckt, aber nicht das direkt Problem gefunden.

              Ja jetzt bekomme ich auch keine Fehler und sogar eine Ausgabe.

              Werde mir aber zur Verständnis den Code nocheinmal genauer unter die Lupe nehmen.Die Sache mit der Tabelle werde ich mir nocheinmal anschauen.

              Danke für die Hilfe

              MfG
              KampfHitsKeks

              1. Hello,

                Werde mir aber zur Verständnis den Code nocheinmal genauer unter die Lupe nehmen.Die Sache mit der Tabelle werde ich mir nocheinmal anschauen.

                Wenn Du Fragen zum Verständnis hast, dann bitte melden.
                Es ist ja ausnahmsweise nicht ausführlich kommentiert im Moment.

                Beim lesen von CSV mit der Funktion fgetcsv() wird nicht auf die einheitliche Ausformung der Datrensätze geachtet. Es können also sowohl welche mit weniger oder mehr Feldern enthalten sein, als auch die Datentypen (CSV kennt eigentlich nur Text und Numerisch" innerhalb der Sätze vermischt/vertauscht  werden. Das ist dann natürlich für die Weiterverarbeitung der Daten lästig.

                Eine CSV-Datei genügt also von alleine nicht den Anforderungen an eine saubere (typenreine) Datentabelle. Diese Forderung zu überprüfen und durchzusetzen wäre also auch noch eine Aufgabe für "hole_daten()".

                Liebe Grüße aus Syburg

                Tom vom Berg

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

                  Beim lesen von CSV mit der Funktion fgetcsv() wird nicht auf die einheitliche Ausformung der Datrensätze geachtet. Es können also sowohl welche mit weniger oder mehr Feldern enthalten sein, als auch die Datentypen (CSV kennt eigentlich nur Text und Numerisch" innerhalb der Sätze vermischt/vertauscht  werden. Das ist dann natürlich für die Weiterverarbeitung der Daten lästig.

                  Eine CSV-Datei genügt also von alleine nicht den Anforderungen an eine saubere (typenreine) Datentabelle. Diese Forderung zu überprüfen und durchzusetzen wäre also auch noch eine Aufgabe für "hole_daten()".

                  habe noch ein bisschen damit gebastelt:

                  #------------------------------------------------------------------------------
                  function holeDaten($filename, &$_buffer, $delete_empty_rows=true, $maxrecsize=2048)
                  {
                     $fh = fopen($filename,'r');
                     if (!$fh) { return 2; }       ## Fehlercode 2 für "kann nicht öffnen" zurückgeben
                     if (!flock($fh, LOCK_SH))
                     {
                         flcose($fh);
                         return 5;                ## Fehlercode 5 für "kann nicht sperren" zurückgeben
                     }

                  $_rec = array();

                  while (false !==($_rec = fgetcsv($fh, $maxrecsize, ';', '"')))
                     {
                         $_buffer[] = $_rec;
                     }
                     fclose($fh);

                  ### Tabelle auf Breite auffüllen.
                     ### dazu benötige wir die breiteste Zeile

                  $cols = 0;
                     foreach($_buffer as $_rec)
                     {
                         $cols = max($cols,count($_rec));
                     }

                  ### Zeilen auf gleiche Breite auffüllen

                  foreach($_buffer as $key => $_rec)
                     {

                  ##       if ($delete_empty_rows and (count($_rec) == 1) and is_null($_rec[0]) )
                  ##       is_null funktioniert hier nicht. Fehler von fgetcsv()

                  if ($delete_empty_rows and (count($_rec) == 1) and (strlen($_rec[0]) == 0) )
                         {
                             echo "Hallo";
                             unset($_buffer[$key]);
                         }
                         else
                         {
                             $plus = $cols - count($_buffer[$key]);
                             if ($plus > 0)
                             {
                                 $_buffer[$key] += array_fill(count($_buffer[$key]), $plus, '');
                             }
                         }
                     }

                  return 0;
                  }
                  #-----------------------------------------------------------------------------

                  und dabei zwei Fehler in fgetcsv() gefunden:

                  1. fgetcsv() gibt auch die numerischen Felder als Strings zurück.
                     Numerische sind solche, die _nicht_ in Anführungszeichen stehen und
                     vollständig numerisch auswertbar sind

                  Ok, damit kann man leben...

                  2. fgetcsv() gint leere Zeilen nicht als Array mit einem Element mit
                     Inhalt NULL zurück, sondern mit einem Element mit dem Wert '' (Leerstring)

                  Das ist nicht so schön, da man dadurch nicht unterscheiden kann zwischen
                     echten Leerzeilen und solchen, die nur ein Feld mit "" (Leerstring) enthalten.

                  die beiden eingebetteten Funktionalitäte für "Breite ermitteln" und "Breite auffüllen" sollte man ggf. auch als einzelne Funktionen deklarieren.

                  Das Auffüllen des Arrays halte ich an dieser Stelle auch nicht unbedingt für sinnvoll, wenn auch für gute Stapelverarbeitung (EVA) konsequent. Es würde reichen, das ggf. später beim Aufbau der HTML-Tabelle zu berücksichtigen, also der Ausgabe.

                  Liebe Grüße aus Syburg

                  Tom vom Berg

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

    Diese Daten sollten dann zeilenweise ausgelesen werden, und als Array zurückgegeben werden

    Du kennst file?

    Dann teste doch mal $x = file("myfile.src"); echo "<pre>"; print_r($x); echo "</pre>";

    Gruesse, Joachim

    --
    Am Ende wird alles gut.
    1. Hello,

      Diese Daten sollten dann zeilenweise ausgelesen werden, und als Array zurückgegeben werden
      Du kennst file?

      Dann teste doch mal $x = file("myfile.src"); echo "<pre>"; print_r($x); echo "</pre>";

      Das ist keine gute Idee für eine sichere Applikation.

      File() ist eine namensbasierte Funktion, mit der es daher sehr schwer ist, ein sauberes konkurrierendes Arbeiten zu ermöglichen.
      Nach POSIX müssen Streams zwar während des Lesens und Schreibens gelockt werden, also bestehende Sperrena uch berücksichtigen, davon haben aber die namensbasierten Funktionen von PHP bisher wenig mitbekommen...

      Außerdem unterliegt das lesen von CSV-Dateien ganz anderen Gesetzen, als sie File() erfüllen kann. Dass im von KampfHitsKeks genannten Datenbeispiel keine Fehler auftreten werden, bedeutet ja nicht, dass er später nicht noch andere Daten hinzufügen will, die dann Fehler verursachen, also die CSV-Regeln einhalten sollten.

      Liebe Grüße aus Syburg

      Tom vom Berg

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

        Nach POSIX müssen Streams zwar während des Lesens und Schreibens gelockt werden,

        verstehe ich jetzt nicht. Sollte man für sowas nicht eh mit flock arbeiten?

        Gruesse, Joachim

        --
        Am Ende wird alles gut.
        1. Hello,

          Nach POSIX müssen Streams zwar während des Lesens und Schreibens gelockt werden,
          verstehe ich jetzt nicht. Sollte man für sowas nicht eh mit flock arbeiten?

          ja, sagte ich doch. File() lässt dies als namensbasierte Hüllfunktion aber nicht direkt zu. Indirektes Locking führt aber meistens zu Fehlern, zumindest bei gemeinsamen Datenbeständen.

          Dafür arbeitet PHP aber mit Streams. File() könnte also mittels einer einzigen Streamanweisung das gesamte File einlesen und puffern. Dann könnte file() auch das nach POSIX vorgeschriebene Locking für Streams beachten.

          Liebe Grüße aus Syburg

          Tom vom Berg

          --
          Nur selber lernen macht schlau
          http://bergpost.annerschbarrich.de