I need to read the last 25 lines from a file (for displaying the most recent log entries). Is there anyway in Ruby to start at the end of a file and read it backwards?
相关问题
- How to specify memcache server to Rack::Session::M
- Why am I getting a “C compiler cannot create execu
- reference to a method?
- ruby 1.9 wrong file encoding on windows
- gem cleanup shows error: Unable to uninstall bundl
相关文章
- How to replace file-access references for a module
- Ruby using wrong version of openssl
- Difference between Thread#run and Thread#wakeup?
- how to call a active record named scope with a str
- “No explicit conversion of Symbol into String” for
- Segmentation fault with ruby 2.0.0p247 leading to
- How to detect if an element exists in Watir
- uninitialized constant Mysql2::Client::SECURE_CONN
Improved version of manveru's excellent seek-based solution. This one returns exactly n lines.
I can't vouch for Ruby but most of these languages follow the C idiom of file I/O. That means there's no way to do what you ask other than searching. This usually takes one of two approaches.
The second way is the one I prefer since, if you choose your first offset wisely, you'll almost certainly only need one shot at it. Log files still tend to have fixed maximum line lengths (I think coders still have a propensity for 80-column files long after their usefulness has degraded). I tend to choose number of lines desired multiplied by 132 as my offset.
And from a cursory glance of Ruby docs online, it looks like it does follow the C idiom. You would use
"ios.seek(25*-132,IO::SEEK_END)"
if you were to follow my advice, then read forward from there.If on a *nix system with
tail
, you can cheat like this:There is a library for Ruby called File::Tail. This can get you the last N lines of a file just like the UNIX tail utility.
I assume there is some seek optimization in place in the UNIX version of tail with benchmarks like these (tested on a text file just over 11M):
I can only imagine the Ruby library uses a similar method.
Edit:
for Pax's curiosity:
still under a second, but if there is a lot of file operations this makes a big difference.
Is the file large enough that you need to avoid reading the whole thing? If not, you could just do
If it is to big, you may need to use
IO#seek
to read from near the end of the file, and continue seeking toward the beginning until you've seen 25 lines.How about:
The performance would be awful over a big file as it iterates twice, the better approach would be the already mentioned read the file and store the last 25 lines in memory and display those. But this was just an alternative thought.