Class: File

Inherits:
Object
  • Object
show all
Defined in:
lib/rexec/reverse_io.rb

Constant Summary collapse

REVERSE_BUFFER_SIZE =
128

Instance Method Summary collapse

Instance Method Details

#read_reverse(length) ⇒ Object

Read a chunk of data and then move the file pointer backwards.

Calling this function multiple times will return new data and traverse the file backwards.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/rexec/reverse_io.rb', line 12

def read_reverse(length)
  offset = tell
  
  if offset == 0
    return nil
  end
  
  start = [0, offset-length].max
  
  seek(start, IO::SEEK_SET)
  
  buf = read(offset-start)
  
  seek(start, IO::SEEK_SET)
  
  return buf
end

#reverse_each_line(sep_string = $/, &block) ⇒ Object

Similar to each_line but works in reverse. Don’t forget to call seek_end before you start!



61
62
63
64
65
66
67
68
69
# File 'lib/rexec/reverse_io.rb', line 61

def reverse_each_line(sep_string=$/, &block)
  line = reverse_gets(sep_string)
  
  while line != nil
    yield line
    
    line = reverse_gets(sep_string)
  end
end

#reverse_gets(sep_string = $/) ⇒ Object

This function is very similar to gets but it works in reverse.

You can use it to efficiently read a file line by line backwards.

It returns nil when there are no more lines.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/rexec/reverse_io.rb', line 37

def reverse_gets(sep_string=$/)
  end_pos = tell
  
  offset = nil
  buf = ""
  
  while offset == nil
    chunk = read_reverse(REVERSE_BUFFER_SIZE)
    return (buf == "" ? nil : buf) if chunk == nil
    
    buf = chunk + buf
    
    offset = buf.rindex(sep_string)
  end
  
  line = buf[offset...buf.size].sub(sep_string, "")
  
  seek((end_pos - buf.size) + offset, IO::SEEK_SET)
  
  return line
end

#seek_endObject

Seek to the end of the file



4
5
6
# File 'lib/rexec/reverse_io.rb', line 4

def seek_end
  seek(0, IO::SEEK_END)
end