Class: File
- Inherits:
-
Object
- Object
- File
- Defined in:
- lib/upm/core_ext.rb,
lib/upm/core_ext/file.rb
Class Method Summary collapse
-
.which(*bins) ⇒ Object
Overly clever which(), which returns an array if more than one argument was supplied, or string/nil if only one argument was supplied.
- .which_is_best?(*bins) ⇒ Boolean
Instance Method Summary collapse
-
#each_line_with_offset ⇒ Object
Iterate over each line of the file, yielding the line and the byte offset of the start of the line in the file.
-
#reverse_each(&block) ⇒ Object
(also: #reverse_each_line)
A streaming ‘reverse_each` implementation.
-
#reverse_each_from_current_pos {|fragment| ... } ⇒ Object
Read each line of file backwards (from the current position.).
-
#reverse_read(length, block_aligned = false) ⇒ Object
Read the previous ‘length` bytes.
-
#reverse_readline ⇒ Object
Read the previous line (leaving ‘pos` at the beginning of the string that was read.).
-
#seek_backwards_to(string, blocksize = 512, rindex_end = -1)) ⇒ Object
(also: #reverse_seek_to)
Scan backwards in the file until ‘string` is found, and set the IO’s
posto the first character after the matched string. -
#seek_end ⇒ Object
Seek to ‘EOF`.
-
#seek_start ⇒ Object
Seek to ‘BOF`.
-
#seek_to(string, blocksize = 512) ⇒ Object
Scan through the file until ‘string` is found, and set the IO’s
posto the first character of the matched string.
Class Method Details
.which(*bins) ⇒ Object
Overly clever which(), which returns an array if more than one argument was supplied, or string/nil if only one argument was supplied.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/upm/core_ext.rb', line 13 def self.which(*bins) results = [] bins = bins.flatten paths = ENV["PATH"].split(":").map { |path| File.realpath(path) rescue nil }.compact.uniq paths.each do |dir| bins.each do |bin| full_path = File.join(dir, bin) if File.exists?(full_path) if bins.size == 1 return full_path else results << full_path end end end end bins.size == 1 ? nil : results end |
.which_is_best?(*bins) ⇒ Boolean
37 38 39 40 |
# File 'lib/upm/core_ext.rb', line 37 def self.which_is_best?(*bins) result = which(*bins.flatten) result.is_a?(Array) ? result.first : result end |
Instance Method Details
#each_line_with_offset ⇒ Object
Iterate over each line of the file, yielding the line and the byte offset of the start of the line in the file
148 149 150 151 152 153 154 155 156 157 |
# File 'lib/upm/core_ext/file.rb', line 148 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 |
#reverse_each(&block) ⇒ Object Also known as: reverse_each_line
A streaming ‘reverse_each` implementation. (For large files, it’s faster and uses less memory.)
11 12 13 14 15 16 |
# File 'lib/upm/core_ext/file.rb', line 11 def reverse_each(&block) return to_enum(:reverse_each) unless block_given? seek_end reverse_each_from_current_pos(&block) end |
#reverse_each_from_current_pos {|fragment| ... } ⇒ Object
Read each line of file backwards (from the current position.)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/upm/core_ext/file.rb', line 53 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 |
#reverse_read(length, block_aligned = false) ⇒ Object
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.)
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/upm/core_ext/file.rb', line 26 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 |
#reverse_readline ⇒ Object
Read the previous line (leaving ‘pos` at the beginning of the string that was read.)
90 91 92 93 94 95 96 97 98 |
# File 'lib/upm/core_ext/file.rb', line 90 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 |
#seek_backwards_to(string, blocksize = 512, rindex_end = -1)) ⇒ Object Also known as: reverse_seek_to
Scan backwards in the file until ‘string` is found, and set the IO’s pos to the first character after the matched string.
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/upm/core_ext/file.rb', line 125 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_end ⇒ Object
Seek to ‘EOF`
76 77 78 |
# File 'lib/upm/core_ext/file.rb', line 76 def seek_end seek(0, IO::SEEK_END) end |
#seek_start ⇒ Object
Seek to ‘BOF`
83 84 85 |
# File 'lib/upm/core_ext/file.rb', line 83 def seek_start seek(0) end |
#seek_to(string, blocksize = 512) ⇒ Object
Scan through the file until ‘string` is found, and set the IO’s pos to the first character of the matched string.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/upm/core_ext/file.rb', line 103 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 |