I am working on a Perl script to read CSV file and do some calculations. CSV file has only two columns, something like below.
One Two
1.00 44.000
3.00 55.000
Without tail, a Perl-only solution isn't that unreasonable.
One way is to seek from the end of the file, then read lines from it. If you don't have enough lines, seek even further from the end and try again.
sub last_x_lines {
my ($filename, $lineswanted) = @_;
my ($line, $filesize, $seekpos, $numread, @lines);
open F, $filename or die "Can't read $filename: $!\n";
$filesize = -s $filename;
$seekpos = 50 * $lineswanted;
$numread = 0;
while ($numread < $lineswanted) {
@lines = ();
$numread = 0;
seek(F, $filesize - $seekpos, 0);
if $seekpos < $filesize; # Discard probably fragmentary line
while (defined($line = )) {
push @lines, $line;
shift @lines if ++$numread > $lineswanted;
}
if ($numread < $lineswanted) {
# We didn't get enough lines. Double the amount of space to read from next time.
if ($seekpos >= $filesize) {
die "There aren't even $lineswanted lines in $filename - I got $numread\n";
}
$seekpos *= 2;
$seekpos = $filesize if $seekpos >= $filesize;
}
}
close F;
return @lines;
}
P.S. A better title would be something like "Reading lines from the end of a large file in Perl".