Re: [Cologne-pm] große Files parsen

Johannes Huettemeister j.huettemeister at googlemail.com
Tue Jan 17 01:37:38 PST 2006


HI Aristoteles,

danke, mein Kuerzen macht das Lesen wirklich nicht leichter ;-)

2006/1/17, A. Pagaltzis <pagaltzis at gmx.de>:
>
> Hi Johannes,
>
> * Johannes Huettemeister <j.huettemeister at googlemail.com> [2006-01-16
> 20:55]:
> >ich hab hier ein Codeschnipsel fabriziert, das funktioniert,
> >aber mit Sicherheit optimiert werden kann.
>
> An Optimierung würde ich erst garnicht denken, jedenfalls nicht
> im Sinne von Geschwindigkeit; der Code ist in der vorliegenden
> Form völlig unlesbar. Ich habe gut 5 Minuten draufstarren müssen,
> bis mir klar war, wie die Bauteile alle zusammenpassen.


Das liegt wohl am Entstehen. Ging zwar sehr schnell aber war viel Trial und
Error und ich hab nachher nicht *sauber* gemacht.


>sysopen (FILE, $filename, O_RDONLY) or die "$!";
> >seek(FILE,$offset,$startpos);
> >
> >my $b = ''; my @f; $togo = 0;
> >for ($curpos = tell(FILE); my $c = read(FILE, $b, 1024, length($b)) ;
> >$curpos = tell(FILE)) {
> >    @f = split(/^/m, $b);
> >      foreach (@f) {
> >        unless (m,\n,) {
> >            $b = $_;
> >            last;
> >        }
> >        do_something_with_line
> >      }
> >      last if ($togo++ == 5000);.
> >}
>
> Vor allem ist der Code fehlerhaft:
>
> 1. Du setzt `$b` nur dann zurück, wenn eine Zeile kein `\n`
>    enthält. Wenn du also einen 1024er-Happen Daten einliest, der
>    zufällig genau am Ende einer Zeile endet, dann wird `$b`
>    nirgendwo geleert, und der nächste Durchlauf der Schleife
>    wird die Daten dann doppelt verarbeiten.
>
>    Das ist es, was mir das Verständnis so erschwert hat: es
>    schien, als wolltest du Daten früherer Durchläufe mehrfach
>    verarbeiten, was offensichtlich ja nicht die Absicht ist.


Das waere ein ganz boeser Bug geworden. Ist zwar beim Test nicht passiert
(fuer 3GB), aber irgendwann sicher.



> 2. Wenn die letzte Zeile der Datei nicht auf ein `\n` endet,
>    schmeisst du sie weg.


Wuerde bei den Inputdaten nicht vorkommen, aber man weiss ja nie.

3. Wenn der letzte der 5000 der 1024er-Happen nicht genau auf
>    ein Zeilenende endet, wirfst du Daten weg, weil die innere
>    Schleife dann zwar diesen Rest nach `$b` zuweist, die äussere
>    aber kein weiteres Mal mehr durchläuft. Und du spulst den
>    Dateicursor auch nicht zurück, um diese Daten beim nächsten
>    Lauf mitzunehmen.
>
> Ausserdem ist es merkwürdig, dass du so obsessiv bei jedem
> Schleifendurchlauf `$curpos` speicherst. Wenn der hier gezeigte
> Code nicht zu unvollständig ist, reicht es, das *ein* einziges
> Mal *nach* der Schleife zu machen.


Das hab ich irgendwo aus dem perl bookshelf, programming perl unter seek
mein ich.

Gruss Jo.

Warum du hier `sysopen` verwendest, ist unklar; und du solltest
> lieber mit lexikalischen Filehandles arbeiten statt Barewords.
>
> Zuguterletzt: statt selber `$togo` zu verwalten, würde ich eher
> eine `foreach`-Schleife von 1-5000 nehmen, aus der ich bei Bedarf
> nach dem Lesen per `last` aussteige.
>
> Summa summarum:
>
>     open my $fh, '<', $filename
>         or die "$!";
>
>     seek $fh, $offset, $startpos;
>
>     # on each iteration, $buf may contain the start of
>     # an incomplete line from the end of the previous
>     # iteration's chunk of data
>     my $buf = '';
>
>     my $chunk_len = 1024;
>
>     for( 1 .. 5000 ) {
>
>         my $read_len = read( $fh, $buf, $chunk_len, length $buf )
>             or last;
>
>         my @line = split /^/m, $buf;
>
>         $buf = ( $line[ -1 ] =~ /\n\z/ ) || ( $read_len != $chunk_len )
>             ? ''
>             : pop @line;
>
>         foreach ( @line ) {
>             do_something_with_line();
>         }
>
>     }
>
>     $curpos = tell $fh;
>
>     # account for unprocessed data
>     $curpos -= do {
>         use bytes;
>         length $buf;
>     };
>
> Gruss,
> --
> #Aristoteles
> *AUTOLOAD=*_;sub _{s/(.*)::(.*)/print$2,(",$\/"," ")[defined
> wantarray]/e;$1};
> &Just->another->Perl->hacker;
> _______________________________________________
> Cologne-pm mailing list
> Cologne-pm at pm.org
> http://mail.pm.org/mailman/listinfo/cologne-pm
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.pm.org/pipermail/cologne-pm/attachments/20060117/3dd80b75/attachment.html


More information about the Cologne-pm mailing list