Since I haven't played with tied file handles before, here's the previous package with the ability to use it either as
an object, or as a tied file handle.
#!/usr/bin/perl
use strict; # https://perlmonks.org/?node_id=11126426
use warnings;
tie *BACKWARDS, 'Tybalt89BackwardsHeReads', $0 or die 'tie failed';
while( <BACKWARDS> )
{
print;
}
package Tybalt89BackwardsHeReads; ####################################
+###
BEGIN
{
*TIEHANDLE = \&new;
*READLINE = \&line;
}
sub line
{
my ($self) = @_;
while( @{ $self->{lines} } == 0 and $self->{where} )
{
my $window = 1024; # window size, adjust to suit
my $pos = $self->{where} - $window;
$pos < 0 and $pos = 0;
seek $self->{fh}, $pos, 0;
read $self->{fh}, my $data, $self->{where} - $pos;
$pos and $data =~ s/^\N*\n(?=.)//s ? ($pos += $+[0]) :
die "increase window size";
$self->{lines} = [ split /^/, $data ];
$self->{where} = $pos;
}
return pop @{ $self->{lines} };
}
sub new
{
my ($self, $filename) = @_;
open my $fh, '<', $filename or die "$! on $filename";
bless { where => ref $filename ? length $$filename : -s $filename,
fh => $fh, lines => [] }, ref $self || $self;
}
1; # so if split off, package ends with true
Replace the $0 with the name of your file. I was just using it for debugging.
Please use this latest version of "sub line", it solves a problem with the fetching the line from the beginning of the file when the window is too small.
|