class File
Public Instance Methods
Iterate over each line of the file, yielding the line and the byte offset of the start of the line in the file
# File lib/epitools/core_ext/file.rb, line 149 def each_line_with_offset return to_enum(:each_line_with_offset) unless block_given? offset = 0 each_line do |line| yield line, offset offset = tell end end
A streaming ‘reverse_each` implementation. (For large files, it’s faster and uses less memory.)
# File lib/epitools/core_ext/file.rb, line 13 def reverse_each(&block) return to_enum(:reverse_each) unless block_given? seek_end reverse_each_from_current_pos(&block) end
Read each line of file backwards (from the current position.)
# File lib/epitools/core_ext/file.rb, line 54 def reverse_each_from_current_pos return to_enum(:reverse_each_from_current_pos) unless block_given? # read the rest of the current line, in case we started in the middle of a line start_pos = pos fragment = readline rescue "" seek(start_pos) while data = reverse_read(4096) lines = data.each_line.to_a lines.last << fragment unless lines.last[-1] == "\n" fragment = lines.first lines[1..-1].reverse_each { |line| yield line } end yield fragment end
Read the previous ‘length` bytes. After the read, `pos` will be at the beginning of the region that you just read. Returns `nil` when the beginning of the file is reached.
If the ‘block_aligned` argument is `true`, reads will always be aligned to file positions which are multiples of 512 bytes. (This should increase performance slightly.)
# File lib/epitools/core_ext/file.rb, line 27 def reverse_read(length, block_aligned=false) raise "length must be a multiple of 512" if block_aligned and length % 512 != 0 end_pos = pos return nil if end_pos == 0 if block_aligned misalignment = end_pos % length length += misalignment end if length >= end_pos # this read will take us to the beginning of the file seek(0) else seek(-length, IO::SEEK_CUR) end start_pos = pos data = read(end_pos - start_pos) seek(start_pos) data end
Read the previous line (leaving ‘pos` at the beginning of the string that was read.)
# File lib/epitools/core_ext/file.rb, line 91 def reverse_readline raise BOFError.new("beginning of file reached") if pos == 0 seek_backwards_to("\n", 512, -2) new_pos = pos data = readline seek(new_pos) data end
Scan backwards in the file until ‘string` is found, and set the IO’s pos
to the first character after the matched string.
# File lib/epitools/core_ext/file.rb, line 126 def seek_backwards_to(string, blocksize=512, rindex_end=-1) raise "Error: blocksize must be at least as large as the string" if blocksize < string.size loop do data = reverse_read(blocksize) if index = data.rindex(string, rindex_end) seek(index+string.size, IO::SEEK_CUR) break elsif pos == 0 return nil else seek(string.size - 1, IO::SEEK_CUR) end end pos end
Seek to ‘EOF`
# File lib/epitools/core_ext/file.rb, line 77 def seek_end seek(0, IO::SEEK_END) end
Seek to ‘BOF`
# File lib/epitools/core_ext/file.rb, line 84 def seek_start seek(0) end
Scan through the file until ‘string` is found, and set the IO’s pos
to the first character of the matched string.
# File lib/epitools/core_ext/file.rb, line 104 def seek_to(string, blocksize=512) raise "Error: blocksize must be at least as large as the string" if blocksize < string.size loop do data = read(blocksize) if index = data.index(string) seek(-(data.size - index), IO::SEEK_CUR) break elsif eof? return nil else seek(-(string.size - 1), IO::SEEK_CUR) end end pos end