Re: end of file!
by mrt (Acolyte) on Jul 26, 2000 at 18:54 UTC
|
Dear Mr. pandey..If you first find the size of the file & then
read the last 100-200 bytes or so..then try to find if there
is a newline character in these bytes..if yes go ahead to
split this with newline character and then take the last
part(in case the end of line is new line character else
any-way you can fix the input record seperator as reqd.) In
case you do not find it then read last 300 bytes or so and
continue till you find it...In this way you'll need only the
minimum memory reqd.finding the size of the file in bytes is
trivial any-way.
As youknow youmay use read(FILEHANDLE,VAR,LENGTH,OFFSET) for ex..
let us suppose you have a file of 5000bytes.. now to get the last
100 characters from it
#!usr/local/bin/perl
open(FILE ,"name_of_the_file_to_be_read");
seek(FILE, 4900,0);
read(FILE,$ab,100); #note the last 100 bytes get stored in $ab
close(FILE);
Now you can very well check for the newline character in $ab
and then No need of any Module etc.... isn't it??
-MRT
| [reply] [Watch: Dir/Any] [d/l] |
|
Wow!! It really works... Thanks..This seems to be one of the
the smartest way one could think of!!! Thanks a lot.........
:-Pandey
| [reply] [Watch: Dir/Any] |
Re: end of file!
by fundflow (Chaplain) on Jul 26, 2000 at 15:41 UTC
|
If the file is small, then the above answer by le is
acceptable.
If you expect the file to be large (such as log file)
and you know the approximate format of the file (e.g. the lines
tend to have max width of 80 characters), then you can use
seek(-81,2) and then use the above solution to get the
last 1.5 lines.
You might want to check if it contains a newline, as otherwise
you probably need to read more.
Here is a code snippet:
open (F,"the file");
seek(F,-81,2);
while(<F>) { $l=$_}
warn if $.<1; # Make sure we read more than one line
| [reply] [Watch: Dir/Any] [d/l] |
|
If you know what the longest the last line in the file is, this can work nicely. You do the seek as above and then put the rest of the file in an array, here is an example:
my @data; # Store the last part of the file
my $length = -10; # enter the longest length of the last line (and add
+ a few bytes to it), then negate it
open (F,"test") || die "Can't open file"; # open the file or die
seek (F,$length,2); # Go back $length
@data = <F>; # Get the rest of the file in @data
print $data[$#data]; # Print the last line
Hope this helps. | [reply] [Watch: Dir/Any] [d/l] |
Re: end of file!
by ColtsFoot (Chaplain) on Jul 26, 2000 at 15:34 UTC
|
If you want a quick and dirty hack and your OS supports
the "tail" command, try the following
print system('tail -1 the_file_you_want_last_line_from');
There may be other more elegant perl ways but this works!!
| [reply] [Watch: Dir/Any] [d/l] |
|
Thanks but I was trying to get solution using perl code itself
i.e. something which reads the file in reverse order..(I know
it can be done throgh tail commond too!!)
| [reply] [Watch: Dir/Any] |
Re: end of file!
by jjhorner (Hermit) on Jul 26, 2000 at 19:38 UTC
|
#!/usr/bin/perl -w
use strict;
my $filename = shift;
my $line;
open (FILE, "$filename") || die "Couldn't open file: $!\n";
do {$line = <FILE>} until eof;
print "$line";
J. J. Horner
Linux, Perl, Apache, Stronghold, Unix
jhorner@knoxlug.org http://www.knoxlug.org/
| [reply] [Watch: Dir/Any] [d/l] |
|
Hi!! Your reply is workable but involves a long process.. as
the seeker of wisdom has told in further comments that the
file is too big, this method may take a lot of time as it
has to read eachline again and again lines and check for
eof.. which the seeker already does not wanted to do, as is very clear from his question. Also for programmes repeating this
code again and again it may be really be unwanted way to
read the last line.. yes perl cook book gives it just an
example and does not recommends this as very good way to
do the same job, infact it expects us to read the codes
and use them in best possible ways depending upon
situation ......
| [reply] [Watch: Dir/Any] |
Re: end of file!
by le (Friar) on Jul 26, 2000 at 15:29 UTC
|
You could slurp the file into an array and then get the last array offset.
@array = <FILE>;
$last_line = $array[-1];
| [reply] [Watch: Dir/Any] [d/l] |
|
Thanks...Yes it is one of the ways but is there some
better way as the file is pretty huge & there is memory
crunch so reading the whole file seems to be really wasting
a lot of memory.. is there something which reads the file in
reverse order.
Thanks-vnpandey
| [reply] [Watch: Dir/Any] |
|
Indeed, there is a module called File::ReadBackwards available
through CPAN. From the description in the man file:
This module reads a file backwards line by line.
It is simple to use, memory efficient and fast.
It supports both an object and a tied handle interface.
It is intended for processing log and other similar text
files which typically have their newest entries appended
to them. By default files are assumed to be plain text and
have a line ending appropriate to the OS. But you can set
the input record separator string on a per file basis.
Autark. | [reply] [Watch: Dir/Any] |
|
Re: end of file!
by japhy (Canon) on Jul 27, 2000 at 23:23 UTC
|
The problem with filesystems is that files are treated as
streams of data, instead of linked lists of lines. If files
were linked lists, then insertion and deletion would be a
snap, as well as traversing the list to a certain line.
As it is, the fastest way is to read X bytes from the end of
the file, and check for the right-most \n character (that is
NOT at the end of the string).
sub last_line {
my ($fref, $r_len) = @_;
my ($last, $chomped) = ("", 0);
$r_len = -$r_len if $r_len > 0;
$r_len ||= -80;
seek $fref, $r_len, 2;
{
my ($buffer,$pos);
read $fref, $buffer, $r_len;
$last = $buffer . $last;
if (($pos = rindex($last,"\n",length($last)-2)) != -1) {
return substr($last,$pos);
}
seek $fref, $r_len * 2, 1;
redo;
}
}
$_="goto+F.print+chop;\n=yhpaj";F1:eval | [reply] [Watch: Dir/Any] [d/l] |
Re: end of file!
by lostsoul (Sexton) on Jul 04, 2007 at 09:14 UTC
|
Is there any way to read a compressed (.gz) file backwards without decompressing the whole file to disk?
I'm trying to read compressed logfiles. | [reply] [Watch: Dir/Any] |