in reply to Re: Last N lines from file (tail)
in thread Last N lines from file (tail)

Except that this doesn't work. Try reading the last N lines from a file with N-5 lines, or a file with < $bufsiz bytes. :)

I had a version that used buffers and was a virtual clone of the algorithm in tail.c, except that I got lost and frustrated in the boundary conditions and really didn't care anymore. Laziness and impatience.

If you want to take a stab at doing this right, be my guest. I just don't want to do the requisite testing, because the test conditions are yucky:

Basically all of the combinations of these. I got all but the last two coded with nice buffering action.

After consideration, I figured I'd let the OS worry about buffering and JFDI. As a matter of fact, if you use getc()instead of sysread() (and seek instead of sysseek, etc..) the STDIO package would take care of most of this buffering nonsense anyway.

sub lastn { my($file, $lines)=@_; my $fh; $lines++; if (! open($fh, $file) ) { print "Can't open $file: $!"; return; } binmode($fh); seek($fh, 0, 2); # Seek to end my $nlcount=0; while($nlcount<$lines) { last unless seek($fh, -1, 1); $_=getc($fh); die unless defined $_; $nlcount++ if ( $_ eq "\n"); last if $nlcount==$lines; last unless (seek($fh, -1, 1)); } $fh; }
There is such as thing as too much optimizing. :)

Update: with example.

Replies are listed 'Best First'.
Re: Re: Re: Last N lines from file (tail)
by SpongeBob (Novice) on Dec 22, 2001 at 02:02 UTC
    One character at a time is still slow, as my benchmarks below showed. This solution still benchmarked at about 4 cps, and my buffered solution gave about 1100 cps.

    Update: BTW, have you looked at File::Tail? It searches from the end of the file also, and if you don't want 'tail -f' behavior (i.e. a blocking read), then you can do:

    my $fh = File::Tail->new(name=>$filename,tail=>$lines); $fh->nowait(1); print $line while $line=$line->read;
    The performance is not horrible on large files, though a bit worse than my function, probably due to the overhead having all sorts of bells and whistles that are not being used.