Class: FLRFile
- Inherits:
-
Object
- Object
- FLRFile
- Includes:
- Enumerable
- Defined in:
- lib/hflr/fl_record_file.rb
Instance Attribute Summary collapse
-
#line_number ⇒ Object
readonly
Returns the value of attribute line_number.
-
#record_template ⇒ Object
readonly
Returns the value of attribute record_template.
Class Method Summary collapse
-
.open(path, mode, record_types, record_layouts, logical_first_column = 0) ⇒ Object
Use when creating a new HFLR file.
Instance Method Summary collapse
-
#<<(record) ⇒ Object
This will take a Hash or Struct orArray; if an Array the record type must be the last element when the record layout has more than one record type.
- #build_record(line) ⇒ Object
- #close ⇒ Object
- #each ⇒ Object
- #fast_get_next_known_line_type ⇒ Object
- #finished? ⇒ Boolean
- #get_next_known_line_type ⇒ Object
-
#get_record_type(line) ⇒ Object
If multiple record types, extract it from the string, otherwise just return the type of this file.
- #in_range?(line_number) ⇒ Boolean
-
#initialize(source, record_types, record_layouts, logical_first_column = 0, extra_columns = nil) ⇒ FLRFile
constructor
A new instance of FLRFile.
- #line_type(line) ⇒ Object
- #next_record ⇒ Object
- #ranges=(ranges) ⇒ Object
- #sequential_get_next_known_line_type ⇒ Object
- #set_fast ⇒ Object
Constructor Details
#initialize(source, record_types, record_layouts, logical_first_column = 0, extra_columns = nil) ⇒ FLRFile
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/hflr/fl_record_file.rb', line 10 def initialize(source, record_types, record_layouts, logical_first_column=0, extra_columns = nil) # Allow record layouts like # {:type1=>[:var1=>1..5,:var2=>7..8],:type2=>[:var1=>1..1,:var2=>3..4]} if record_layouts.values.first.is_a? Hash record_layouts = create_layouts(record_layouts) end @line_number = 0 @file = source @record_type_labels=record_types @record_type_symbols = record_types.is_a?(Hash) ? record_types.invert : :none if extra_columns then @record_template = HFLR::RecordTemplate.create(record_layouts, @record_type_symbols, logical_first_column, extra_columns) else @record_template = HFLR::RecordTemplate.create(record_layouts, @record_type_symbols, logical_first_column) end end |
Instance Attribute Details
#line_number ⇒ Object (readonly)
Returns the value of attribute line_number.
8 9 10 |
# File 'lib/hflr/fl_record_file.rb', line 8 def line_number @line_number end |
#record_template ⇒ Object (readonly)
Returns the value of attribute record_template.
8 9 10 |
# File 'lib/hflr/fl_record_file.rb', line 8 def record_template @record_template end |
Class Method Details
.open(path, mode, record_types, record_layouts, logical_first_column = 0) ⇒ Object
Use when creating a new HFLR file
174 175 176 177 178 179 180 181 182 |
# File 'lib/hflr/fl_record_file.rb', line 174 def self.open(path, mode, record_types, record_layouts, logical_first_column=0) file = File.open(path, mode) begin hflr_file = new(file, record_types, record_layouts, logical_first_column) yield hflr_file ensure file.close end end |
Instance Method Details
#<<(record) ⇒ Object
This will take a Hash or Struct orArray; if an Array the record type must be the last element when the record layout has more than one record type.
159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/hflr/fl_record_file.rb', line 159 def <<(record) if record.is_a? Array record_type = @record_type_symbols == :none ? @record_template.keys.first : record.last @file.puts @record_template[record_type].build_line(record) else record_type = @record_type_symbols == :none ?@record_template.keys.first : record[:record_type] if @record_template[record[:record_type]] == nil then raise "Record type problem in output: #{record[:record_type].to_s} type on record, #{@record_template.keys.join(",")} types of templates" end @file.puts @record_template[record_type].build_line(record) end end |
#build_record(line) ⇒ Object
79 80 81 82 83 84 |
# File 'lib/hflr/fl_record_file.rb', line 79 def build_record(line) return nil if line.nil? record_type = line_type(line) raise "Unknown record type at line #{@line_number.to_s}" if record_type == :unknown return @record_template[record_type].build_record(line.chomp) end |
#close ⇒ Object
68 69 70 |
# File 'lib/hflr/fl_record_file.rb', line 68 def close @file.close end |
#each ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/hflr/fl_record_file.rb', line 143 def each @line_number = 1 if @fast yield(next_record) until finished? else @file.each_line do |line| unless line_type(line) == :unknown || !in_range?(@line_number) data = build_record(line) yield data end end end end |
#fast_get_next_known_line_type ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/hflr/fl_record_file.rb', line 99 def fast_get_next_known_line_type unless @current_buffer.nil? && (@offsets.nil? || @offsets.empty?) if @current_buffer.nil? chunk = @offsets.shift puts "shifting first chunk #{chunk.inspect}" @file.pos = chunk.pos @current_buffer=@file.read(chunk.width) record= @current_buffer.slice(@position,@width) puts "Record was from #{@position} width of #{@width}" puts "Getting record: #{record}" @position += @width puts "Position incremented to #{@position}" puts "Current buffer size: #{@current_buffer.size}" @current_buffer = nil if @position >= @current_buffer.size puts "current_buffer changed to #{@current_buffer}" return record else record= @current_buffer.slice(@position,@width) puts "Getting subsequent record: #{record}" @position += @width @current_buffer = nil if @position >= @current_buffer.size return record end else puts "At end of all chunks" nil end end |
#finished? ⇒ Boolean
60 61 62 63 64 65 66 |
# File 'lib/hflr/fl_record_file.rb', line 60 def finished? if @fast @offsets.empty? && @current_buffer.nil? else @file.eof? end end |
#get_next_known_line_type ⇒ Object
95 96 97 |
# File 'lib/hflr/fl_record_file.rb', line 95 def get_next_known_line_type @fast ? fast_get_next_known_line_type : sequential_get_next_known_line_type end |
#get_record_type(line) ⇒ Object
If multiple record types, extract it from the string, otherwise just return the type of this file
73 74 75 76 77 |
# File 'lib/hflr/fl_record_file.rb', line 73 def get_record_type(line) return nil if line.nil? return nil if line.strip.empty? @record_type_labels.is_a?(Hash) ? @record_type_labels[line[0..0]] : @record_type_labels end |
#in_range?(line_number) ⇒ Boolean
56 57 58 |
# File 'lib/hflr/fl_record_file.rb', line 56 def in_range?(line_number) @ranges ? !!(@ranges.detect{|r| r.member?(line_number)}) : true end |
#line_type(line) ⇒ Object
90 91 92 93 |
# File 'lib/hflr/fl_record_file.rb', line 90 def line_type(line) record_type = get_record_type(line) return record_type ? record_type : :unknown end |
#next_record ⇒ Object
86 87 88 |
# File 'lib/hflr/fl_record_file.rb', line 86 def next_record build_record(get_next_known_line_type) end |
#ranges=(ranges) ⇒ Object
44 45 46 47 48 49 50 51 52 53 |
# File 'lib/hflr/fl_record_file.rb', line 44 def ranges=(ranges) @fast or raise "Cannot read selected ranges because input file has multiple record types #{@record_type_labels.to_s}" unless ranges.first.is_a?(Range) raise "You specified a #{ranges.first.class.to_s} instead of a range in the list of ranges. Use (a..b) to specify a range." end @offsets =offsets_to_read(ranges, @width) puts "Chunks of data #{@offsets.inspect}" @ranges = ranges end |
#sequential_get_next_known_line_type ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/hflr/fl_record_file.rb', line 129 def sequential_get_next_known_line_type line = @file.gets @line_number+=1 record_type = line_type(line) while !finished? && (!in_range?(@line_number) || record_type == :unknown) line = @file.gets @line_number+=1 record_type = line_type(line) end record_type == :unknown ? nil : line end |
#set_fast ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/hflr/fl_record_file.rb', line 27 def set_fast @fast = !@record_type_labels.is_a?(Hash) unless @fast raise "Cannot set fast mode with more than one record type." end if @fast @width = get_record_width_from_file puts "record width #{@width.to_s}" records_to_take = 50000001 / @width puts "records_to_take: #{records_to_take}" @buffer_size = @width * records_to_take puts "Buffer size: #{@buffer_size}" @position=0 @current_buffer=nil end end |