finding last line in a file

T

Ted Flethuseo

Hi everyone,

Is there a one line command to do this?

I mean currently I use

File.foreach(inFile) do |line|
...
done

I could do this with a counter, but that is SO UGLY, and I want to do an
operation on that very last line.

Regards,
Ted.
 
P

prasad c

[Note: parts of this message were removed to make it a legal post.]

last_line = ''
IO.popen("tail -n 1 #{file_name}") { |f| last_line = f.gets }

Regards,
Prasad C
 
R

Robert Klemme

Oops... typo. I meant readlines. With it you can do something like
File.readlines(f).last

This is as inefficient as using File.foreach because it will read the
whole file. I believe Ted was looking for a more efficient solution.

Ted, if you want to do this in Ruby and not resort to tail you can use
IO#seek to seek to the end of the file and read backwards until you have
read more than one line.

Kind regards

robert
 
J

Jesús Gabriel y Galán

This is as inefficient as using File.foreach because it will read the who= le
file. =A0I believe Ted was looking for a more efficient solution.

Ted, if you want to do this in Ruby and not resort to tail you can use
IO#seek to seek to the end of the file and read backwards until you have
read more than one line.

I think this is the algorithm used by James Gray in Elif:

http://elif.rubyforge.org/

From those docs:

" gets(sep_string =3D $/)

The second half on the Elif algorthim (see Elif::new). This method
returns the next line of the File, working from the end to the
beginning in reverse line order.

It works by moving the file pointer backwords MAX_READ_SIZE at a time,
storing seen lines in @line_buffer. Once the buffer contains at least
two lines (ensuring we have seen on full line) or the file pointer
reaches the head of the File, the last line from the buffer is
returned. When the buffer is exhausted, this will throw nil (from the
empty Array)."


Jesus.
 
U

Urabe Shyouhei

This is as inefficient as using File.foreach because it will read the
whole file. I believe Ted was looking for a more efficient solution.

Then how about:

File.open(f).each_line.inject(nil){|x,y|y}

Slower than my first answer though.
 
R

Robert Klemme

2010/7/22 Urabe Shyouhei said:
Then how about:

File.open(f).each_line.inject(nil){|x,y|y}

Slower than my first answer though.

This still reads in the whole file plus you do not close the File
object properly. A solution that is efficient for large files will
use File#seek to move position to the end of the file and go backwards
from there.

Cheers

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
T

Ted Flethuseo

Robert said:
This is as inefficient as using File.foreach because it will read the
whole file. I believe Ted was looking for a more efficient solution.

Ted, if you want to do this in Ruby and not resort to tail you can use
IO#seek to seek to the end of the file and read backwards until you have
read more than one line.

Kind regards

robert

Interesting, the problem is how to find how far back I need to go in the
seek (automatically of course)

f = File.new("testfile")
f.seek(-13, IO::SEEK_END) #=> 0
f.readline #=> "And so on...\n"

Ted.
 
U

Urabe Shyouhei

This still reads in the whole file plus you do not close the File
object properly.

I'm sure you know how to do that properly.
A solution that is efficient for large files will
use File#seek to move position to the end of the file and go backwards
from there.

No, that can't work -- or that works only when you are sticking on the ASCII
character set. Multibyte encodings are not safe to read backwards
(sometimes). The only safe way is to read the whole content from the
beginning, at least one time.
 
X

Xavier Noria

And says nothing about multiligualization because M17N cannot be achieved by
the approach, theoretically.

So in general you can't detect character boundaries going backwards?
You can always have cut characters and still have a valid buffer?
 
R

Robert Klemme

No, that can't work -- or that works only when you are sticking on the ASCII
character set. Multibyte encodings are not safe to read backwards
(sometimes). The only safe way is to read the whole content from the
beginning, at least one time.

Good point. Although pragmatically for fixed width and UTF-8 encoded
files it will work and the performance gains for large files are
significant enough to warrant this approach.

Cheers

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top