stack1
stack1

Reputation: 1022

How to read a file backwards and then forwards with ruby?

I have svn log files which are a few kb to 1 mb, usually kb. They contain zero, one or more of the below blocks of text:

---------------------------------
r3457 | programmer1 | 03.20.2015
changed file1.txt
added file7.txt
etc...
team1: adding new feature to app
---------------------------------

I want to get the last check-in in each file. In the above example, last check in is 3457.

So, for this, I am going to read a file from bottom, keep reading upwards till i find a dashed line. Then, I will move forwards and read the next line which has the last check in.

How do I do this ? I read a bit about elif but could not figure out the api. I also tried one so post, but its not clear - Easy question: Read file, reverse it and write to another file in Ruby

I can do this, but I don't want to write it to another file.

o = File.new("ouput.txt", "w+")

File.new("my_file.txt").lines.reverse_each { |line|
    o.puts line 
}
o.close

Thanks a million !

Upvotes: 1

Views: 1385

Answers (2)

steenslag
steenslag

Reputation: 80065

Few kb to 1 mb, no need to do complicated byte level file reading. Just read the lines in an array and get the last dashed line using rindex.

ar = File.readlines('test.txt')
# dashes_idx = ar.rindex("---------------------------------\n")
dashes_idx = ar.rindex{|line| line.end_with?("----------\n")}
p ar[dashes_idx + 1].split(" | ").first

Upvotes: 2

knut
knut

Reputation: 27845

I made a log-analyzer like this:

Bytes = 10000
File.open(filename){|f|
  puts "Open #{f.path}, get last #{Bytes} bytes"
  f.seek(-Bytes, IO::SEEK_END  )
  puts f.readlines
}

This snipplet reads the last 10000 Bytes of the file (see the minus before Bytes) and prints it.

Just estimate the size of one record and try to read the last x entries. Inside this entries you can go for the last one.

One propose:

N      = 1000 #average size of one record
File.open(filename){|f|
  puts "Get approx. get last 5 records"
  f.seek(-(5*N), IO::SEEK_END  )
  tail = f.read
  last_record = tail.split('----------').last
}

Upvotes: 1

Related Questions