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