Reading total lines of file then displaying in reverse?

How would I use File or IO to read all the lines of a
file, then display the contents in reverse?

Its for a simple log reading script, which I would
like to have read the total lines, then display with
the latest entries first, and show x amount of log
entries per page.

I'm currently just dumping the whole, or part of the
log with:

···

======
IO.readlines("my.log")[1..49].each_with_index do

line, index|

======

I guess I would have to count all lines, then assign a
variable to the last number it counts, and then work
in reverse from this variable... hmmm. I'm not
sure:P

Any ideas?

___________________________________________________________
How much free photo storage do you get? Store your holiday
snaps for FREE with Yahoo! Photos http://uk.photos.yahoo.com

Tristan Knowles wrote:

How would I use File or IO to read all the lines of a
file, then display the contents in reverse?

something like this?

File.readlines("my.log").reverse.each{|l| puts l}

RY
Stefan

if i understand you correctly:

   harp:~ > cat a.txt
   42
   1
   2
   3
   4
   5
   6
   7
   8
   9
   10

   harp:~ > cat a.rb

   lines = IO::readlines(ARGV.shift)

   page_separator = '=' * 79
   page_size = 5
   length = $.
   n_pages = (length / page_size) + 1

   catch('done') do
     n_pages.times do
       page_size.times do
         throw 'done' if lines.empty?
         print lines.pop
       end
       puts page_separator
     end
   end

   harp:~ > ruby a.rb a.txt
   10
   9
   8
   7
   6

···

On Mon, 18 Jul 2005, Tristan Knowles wrote:

How would I use File or IO to read all the lines of a
file, then display the contents in reverse?

Its for a simple log reading script, which I would
like to have read the total lines, then display with
the latest entries first, and show x amount of log
entries per page.

I'm currently just dumping the whole, or part of the
log with:

======
IO.readlines("my.log")[1..49].each_with_index do
>line, index|

I guess I would have to count all lines, then assign a
variable to the last number it counts, and then work
in reverse from this variable... hmmm. I'm not
sure:P

Any ideas?

   ===============================================================================
   5
   4
   3
   2
   1
   ===============================================================================
   42

'$.' is always the number of lines read after an IO::readlines.

hth.

-a
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

Tristan Knowles wrote:

How would I use File or IO to read all the lines of a
file, then display the contents in reverse?

Its for a simple log reading script, which I would
like to have read the total lines, then display with
the latest entries first, and show x amount of log
entries per page.

Given the size of log files and the expense of reversing arrays, I'd be inclined to index the thing. Define a class to wrap access to the file, and make it store an array of file offsets for the starts of the lines of the log file. It can keep an internal timestamp to know when the log file has changed and the array needs to have more entries appended to it; and skipping to the end and reading lines and adding the entries will be a very cheap operation.

Then you define dump_log(numlines, offsetfromend) to seek to offsetarray[offsetarray.length - offsetfromend], read in numlines to an array, and dump it out using reverse_each.

Even if you have to marshal your index data between calls to your program, that should still be faster than trawling through (say) my 12,484 lines of CUPS error log every time the user hits "next page"...

mathew
[ Call me old, but I don't like the 'A few MB is nothing, just slurp in
   the whole log file' approach. ]

···

--
<URL:http://www.pobox.com/~meta/&gt;
          WE HAVE TACOS

Cool. That reverses the value of the lines ordered,
but still lists the line numbers from 0 -> x.

Anyway to reverse this also, x -> 0?

Thanks again.

···

--- Stefan Holst <mail@s-holst.de> wrote:

Tristan Knowles wrote:
> How would I use File or IO to read all the lines
of a
> file, then display the contents in reverse?

something like this?

File.readlines("my.log").reverse.each{|l| puts l}

RY
Stefan

___________________________________________________________
Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com

Hi --

···

On Mon, 18 Jul 2005, Stefan Holst wrote:

Tristan Knowles wrote:

How would I use File or IO to read all the lines of a
file, then display the contents in reverse?

something like this?

File.readlines("my.log").reverse.each{|l| puts l}

I believe that's identical to:

   puts File.readlines("my.log").reverse

David

--
David A. Black
dblack@wobblini.net

Stefan Holst wrote:

Tristan Knowles wrote:
> How would I use File or IO to read all the lines of a
> file, then display the contents in reverse?

something like this?

File.readlines("my.log").reverse.each{|l| puts l}

RY
Stefan

There's Array#reverse_each which would save an
unnecessary array reversal :slight_smile:

File.readlines("my.log").reverse_each{|l| puts l}

daz

For my case, it now looks like this:

lines = IO.readlines("my.log").reverse.each_with_index
do |line, index|

I'm trying to use .length somewhere now to count the
number of lines.

Tristan

···

--- "David A. Black" <dblack@wobblini.net> wrote:

> File.readlines("my.log").reverse.each{|l| puts l}

I believe that's identical to:

   puts File.readlines("my.log").reverse

___________________________________________________________
Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com

Hi --

File.readlines("my.log").reverse.each{|l| puts l}

I believe that's identical to:

   puts File.readlines("my.log").reverse

For my case, it now looks like this:

lines = IO.readlines("my.log").reverse.each_with_index
do |line, index|

I'm trying to use .length somewhere now to count the
number of lines.

One possibility:

   class Array
     def map_with_index
       res =
       each_with_index {|e,i| res << yield(e, i) }
       res
     end
   end

   puts File.readlines("my.log").map_with_index {|*a| a }.reverse

(Not optimally efficient, I think, but anyway.)

David

···

On Mon, 18 Jul 2005, Tristan Knowles wrote:

--- "David A. Black" <dblack@wobblini.net> wrote:

--
David A. Black
dblack@wobblini.net

lines.size will give you the number of lines. Are you trying to do something
like this?

    lines = File.readlines("my.log")

    lines.reverse.each_with_index do |line, index|
      index = lines.size - index
      printf "%5d %s", index, line
    end

Or:

    c = lines.size
    lines.reverse_each do |line|
      printf "%5d %s", c, line
      c -= 1
    end

Or the fancy way, if you want to iterate using each_with_index but not
create an intermediate reversed copy of the array:

    require 'enumerator'
    lines.to_enum(:reverse_each).each_with_index do |line, index|
      index = lines.size - index
      printf "%5d %s", index, line
    end

Regards,

Brian.

···

On Mon, Jul 18, 2005 at 09:06:26PM +0900, Tristan Knowles wrote:

For my case, it now looks like this:

lines = IO.readlines("my.log").reverse.each_with_index
do |line, index|

I'm trying to use .length somewhere now to count the
number of lines.