Finding last line in a file

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.

last_line = ‘’
IO.popen(“tail -n 1 #{file_name}”) { |f| last_line = f.gets }

Regards,
Prasad C

Take a look at the doc for File.readline.

(2010/07/22 14:08), Urabe S. wrote:

Take a look at the doc for File.readline.

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

On Thu, Jul 22, 2010 at 8:35 AM, Robert K.
[email protected] wrote:

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.

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

http://elif.rubyforge.org/

From those docs:

" gets(sep_string = $/)

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.

On 07/22/2010 07:10 AM, Urabe S. wrote:

(2010/07/22 14:08), Urabe S. wrote:

Take a look at the doc for File.readline.

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

(2010/07/22 15:35), Robert K. wrote:

On 07/22/2010 07:10 AM, Urabe S. wrote:

(2010/07/22 14:08), Urabe S. wrote:

Take a look at the doc for File.readline.

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.

Then how about:

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

Slower than my first answer though.

2010/7/22 Urabe S. [email protected]:

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

(2010/07/22 22:06), Robert K. wrote:

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.

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.

Check the elif gem, by James Edward G. II.

It is a port of File::ReadBackwards, whose documentation explains the
approach:

http://search.cpan.org/~uri/File-ReadBackwards-1.04/ReadBackwards.pm#DESIGN

– fxn

(2010/07/22 23:33), Xavier N. wrote:

Check the elif gem, by James Edward G. II.

It is a port of File::ReadBackwards, whose documentation explains the approach:

http://search.cpan.org/~uri/File-ReadBackwards-1.04/ReadBackwards.pm#DESIGN

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

Maybe that’s OK for Ted. I’m living in a different world than you
perhaps.

Robert K. wrote:

On 07/22/2010 07:10 AM, Urabe S. wrote:

(2010/07/22 14:08), Urabe S. wrote:

Take a look at the doc for File.readline.

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

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.

On Thu, Jul 22, 2010 at 5:36 PM, Urabe S. [email protected]
wrote:

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?

On Jul 22, 2010, at 10:36 AM, Urabe S. wrote:

(2010/07/22 23:33), Xavier N. wrote:

Check the elif gem, by James Edward G. II.

It is a port of File::ReadBackwards, whose documentation explains the approach:

http://search.cpan.org/~uri/File-ReadBackwards-1.04/ReadBackwards.pm#DESIGN

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

Yes, I wrote it before Ruby 1.9’s m17n engine. I only use it on ASCII
logs, where it works fine. I would not recommend it for encoded data.

James Edward G. II

On 22.07.2010 16:22, Urabe S. wrote:

(2010/07/22 22:06), Robert K. wrote:

Then how about:

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

Slower than my first answer though.

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.

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