How to read the prevous line of a file. The opposite of IO.gets.I initially thought to set IO.lineno to the line number I wanted to read but that doesn't work as expect. How do you actually read the previous line?
There are a couple of ways, it depends on how much information you have at your disposal. If you know the length of the last line you read in you can take the easiest approach which would be
# assume f is the File object
len = last_line_length
f.seek -len, IO::SEEK_CUR
Of course, if you are not provided that information things become a little less nice. You could use the same approach as above to walk backwards (one byte at a time) until you hit a newline marker or take lineno
and read from the beginning. Something like
lines = f.lineno
f.rewind
(lines - 1).times { f.gets }
However, as far as I know, there is no direct mechanism to just go back 1 N
where N
represents a line.
As an aside, you should know that while you can write to File.lineno
doing so does not actually affect the position in the file and it also ruins the accuracy of the variable for reads after that point.
One simple way is to remember the previous line you read:
prev = nil
File.foreach('_vimrc') do |line|
p [line, prev] # do whatever processing here
prev = line
end
Saw an excellent suggestion on comp.lang.ruby -- use IO.tell to keep track of the position of each line in the file so you can seek directly to it:
File.open "foo" do |io|
idx = [io.tell]
while l = io.gets
p l
idx << io.tell
end
end
The Elif gem has a gets method that is the opposite of IO.gets.
$ sudo gem install elif
$ irb
require "elif"
last_syslog = Elif.open('/var/log/syslog') { |file| file.gets }