jcasper: Datei zeilenweise einlesen.

Hallo Forum,

sehr oft habe ich hier schon den einen oder anderen wertvollen Tipp erhalten. Diesmal weiß ich mir aber keine Rat mehr und bin am Ende mit meinem Latein.

Ich habe ein HTML Formular, welches mir ein File über die Funktion <input type=FILE> übergibt. Die darin enthalten Daten möchte ich nur auslesen aber nicht schreiben oder speichern.

Folgenden Code habe ich bereits:

  
my $SPM_handle = $cgi -> upload('SPM');  
my @extensions = qw(txt xls xlsx csv);  
my $i = 0;  
my $file_enabled = "yes";  
  if (($SPM_handle ne "") && ($file_enabled eq "yes")) {  
    if (!grep($fileext,@extensions)) {  
      print "The file has an invalid format! (wrong extension)!<br />\n";  
    } else {  
      while (read($SPM_handle, $buffer, 1024 )) {  
        # only for testing  
        # print "<p>" . $buffer . "</p><hr /><br />";  
        if($i == 0) {  
          # save to $fields (header fields)  
          $fields = $buffer;  
        } else {  
          # start with line 2, save to $data_compl  
          $data_compl[$i] = $buffer;  
        }  
        $i++;  
      }  
    }  
    $counts = $i - 1;  
  }  

Was mir jetzt die Kopfzerbrechen bereitet, ist die Tatsache, dass keine Zeilenenden erkannt werden. Alle Spalten sind ";" getrennt und am Ende steht ein CR LF. Aber wenn ich ein CSV File lade, wird die Zeilenlänge nur in Abhängigkeit des LENGHT Attributs bei read() definiert. Wie bringe ich read() dazu immer genau bis zum Zeilenende (CR LF) zu lesen?

Für Eure Hilfe vorab schon einmal Danke!
ciao Jörg

  1. Moin Namensvetter,
    "read" liest per Defintion erstmal so viel wie es kriegen kann. Da müsstest Du eine eigene "Zeilenende-Erkennung" einbauen (split nach \r\n oder so).

    Es gibt aber eine einfachere Möglichkeit:

      
    my @lines = <FILE_HANDLE>;  
    
    

    (also den Filehandle in <> schreiben).
    Damit kriegst Du die Zeilen säuberlich in ein Array.

    Nachteil: Alle Daten werden AUF EINMAL in das Array gestopft. Bei großen Dateien -> hoher Speicherbedarf,

    Hope that helps,

    Jörg

    1. Hallo Jörg!

      Bei großen Dateien -> hoher Speicherbedarf,

      Oder man benutzt Tie::File: »The file is not loaded into memory, so this will work even for gigantic files.«

      Hope that helps,

      Hope that too ;)

      Viele Grüße aus Frankfurt/Main,
      Patrick

      --
      _ - jenseits vom delirium - _

         Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
      J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
    2. Hallo Namensvetter zurück ;-),

      bislang bin ich davon ausgegangen, dass ich ein Filehandle nur für gespeicherte Dateien verwenden kann. Aber ich werde es nochmal so versuchen.
      Die Zeilenerkennung funktioniert ansonsten jetzt.

      Moin Namensvetter,
      "read" liest per Defintion erstmal so viel wie es kriegen kann. Da müsstest Du eine eigene "Zeilenende-Erkennung" einbauen (split nach \r\n oder so).

      Es gibt aber eine einfachere Möglichkeit:

      my @lines = <FILE_HANDLE>;

      
      > (also den Filehandle in <> schreiben).  
      > Damit kriegst Du die Zeilen säuberlich in ein Array.  
      >   
      > Nachteil: Alle Daten werden AUF EINMAL in das Array gestopft. Bei großen Dateien -> hoher Speicherbedarf,  
      >   
        
      Die Dateien sind per Script begrenzt auf 2MB. Aber eigentlich sind diese durchschnittlich nur max. 750k - 1M groß.  
        
      
      > Hope that helps,  
        
      I hope it also! ;-)  
        
      
      >   
      > Jörg  
      >   
        
      ciao Jörg (aus Sachsen)
      
    3. Hi,

      my @lines = <FILE_HANDLE>;

      
      > Nachteil: Alle Daten werden AUF EINMAL in das Array gestopft. Bei großen Dateien -> hoher Speicherbedarf,  
        
      while (<FILE\_HANDLE>)  
      {  
      # $\_ enthält jetzt genau eine Zeile  
      }  
        
      cu,  
      Andreas
      
      -- 
      [Warum nennt sich Andreas hier MudGuard?](http://MudGuard.de/)  
      [O o ostern ...](http://ostereier.andreas-waechter.de/)  
        
      Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.  
      
      
  2. Hallo Forum,

    das mit dem CR LF habe ich schon mal geklärt.
    (auch eine Suchmaschine will richtig gefüttert sein)

      
    
    > my $SPM_handle = $cgi -> upload('SPM');  
    > my @extensions = qw(txt xls xlsx csv);  
    > my $i = 0;  
    > my $file_enabled = "yes";  
    >   if (($SPM_handle ne "") && ($file_enabled eq "yes")) {  
    >     if (!grep($fileext,@extensions)) {  
    >       print "The file has an invalid format! (wrong extension)!<br />\n";  
    >     } else {  
    >       while (read($SPM_handle, $buffer, 1024 )) {  
    >         # only for testing  
      
               my $complfile = $buffer;  
               # replace CR LF with <br00>  
               $complfile =~ s/\015\012|\015|\012/<br00>/g;  
               my @lines = split(/<br00>/,$complfile);  
               foreach $i (0..$#lines) {  
                 if ($i == 0) {  
                   $headline = $lines[$i];  
                 } else {  
                   $fieldlines[$i-1] = $lines[$i];  
                 }  
               } $i = 0;  
               @headline_sep = split(/;/,$headline);  
               foreach $i (0..$#headline_sep) {  
                 print $headline_sep[$i];  
                 if ($i != $#headline_sep) {  
                   print " :: ";  
                 }  
               } print "<br />"; $i = 0;  
      
    
    >       }  
    >     }  
    >     $counts = $i - 1;  
    >   }  
    
    

    Was ich jetzt noch suche, ist die Möglichkeit das von mir gefüllt Array @fieldlines aufzusplitten.
    Dafür hatte ich mir folgendes überlegt:

      
      foreach $i (0..$#fieldlines) {  
        my @fieldline_sep_[$i] = split(/;/,$fieldlines[$i]);  
      }  
    
    

    So das ich am Ende mehrere Arrays "@fieldline_sep_0 ... 1,2" und so weiter erhalte. Über $#fieldlines + 1 würde ich die Anzahl erhalten und weiß so, wie viele Arrays ich bekommen habe.
    Wie aber kann ich diese Arrays deklarieren? "@fieldline_sep_[$i]" functioniert leider nicht ;-) (wäre ja auch zu einfach).

    Für Eure Hilfe vorab schon einmal Danke!
    ciao Jörg

    1. Hallo jcasper!

      Was ich jetzt noch suche, ist die Möglichkeit das von mir gefüllt Array @fieldlines aufzusplitten.

      Du meinst sicher: »die Möglichkeit, jedes Element des von mir gefüllten Array @fieldlines in weitere Arrays aufzusplitten«?

      Warum nicht gleich dafür sorgen, dass die Elementen von @fiedlines bereits beim Füllen Arrays sind und so aus @fiedlines einen AoA machen?

      Willkommen bei der wunderbaren Welt komplexer Datenstrukturen!

      Viele Grüße aus Frankfurt/Main,
      Patrick

      --
      _ - jenseits vom delirium - _

         Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
      J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
      1. Hallo Patrick,

        Hallo jcasper!

        »» Was ich jetzt noch suche, ist die Möglichkeit das von mir gefüllt Array @fieldlines aufzusplitten.

        Du meinst sicher: »die Möglichkeit, jedes Element des von mir gefüllten Array @fieldlines in weitere Arrays aufzusplitten«?

        Deutsche Sprache schwere Sprache! ;-)

        Warum nicht gleich dafür sorgen, dass die Elementen von @fiedlines bereits beim Füllen Arrays sind und so aus @fiedlines einen AoA machen?

        Willkommen bei der wunderbaren Welt komplexer Datenstrukturen!

        Au Backe .. bloß gut das Wochenende ist, da habe ich genügend Zeit mir das mal genauer anzusehen ..!

        Viele Grüße aus Frankfurt/Main,
        Patrick

        Vielen Dank Patrick und
        viele Grüße aus Sachsen nach Hessen.

        ciao Jörg