lib/dbf/reader.rb in dbf-0.2.0 vs lib/dbf/reader.rb in dbf-0.3.0

- old
+ new

@@ -8,10 +8,13 @@ DATE_REGEXP = /([\d]{4})([\d]{2})([\d]{2})/ VERSION_DESCRIPTIONS = {"02" => "FoxBase", "03" => "dBase III without memo file", "04" => "dBase IV without memo file", "05" => "dBase V without memo file", "30" => "Visual FoxPro", "31" => "Visual FoxPro with AutoIncrement field", "7b" => "dBase IV with memo file", "83" => "dBase III with memo file", "8b" => "dBase IV with memo file", "8e" => "dBase IV with SQL table", "f5" => "FoxPro with memo file", "fb" => "FoxPro without memo file"} + + class DBFError < StandardError; end + class UnpackError < DBFError; end class Reader attr_reader :field_count attr_reader :fields @@ -83,16 +86,16 @@ else record[field.name] = unpack_float(field) rescue nil end when 'D' # date raw = unpack_string(field).to_s.strip - record[field.name] = raw.empty ? nil : Date.new(*raw.match(DATE_REGEXP).to_a.slice(1,3).map {|n| n.to_i}) rescue nil + record[field.name] = raw.empty? ? nil : Date.new(*raw.match(DATE_REGEXP).to_a.slice(1,3).map {|n| n.to_i}) rescue nil when 'M' # memo starting_block = unpack_integer(field) record[field.name] = starting_block == 0 ? nil : memo(starting_block) rescue nil when 'L' # logical - record[field.name] = unpack_string(field) =~ /(y|t)/i ? true : false rescue false + record[field.name] = unpack_string(field) =~ /^(y|t)$/i ? true : false rescue false else record[field.name] = unpack_string(field) end end record @@ -119,12 +122,16 @@ def seek_to_record(index) seek(@record_length * index) end + def unpack_field(field) + @data_file.read(field.length).unpack("a#{field.length}") + end + def unpack_string(field) - @data_file.read(field.length).unpack("a#{field.length}").to_s + unpack_field(field).to_s end def unpack_integer(field) unpack_string(field).to_i end @@ -133,13 +140,16 @@ unpack_string(field).to_f end end + class FieldError < StandardError; end + class Field attr_accessor :name, :type, :length, :decimal def initialize(name, type, length, decimal) + raise FieldError, "field length must be greater than 0" unless length > 0 self.name, self.type, self.length, self.decimal = name, type, length, decimal end def name=(name) @name = name.gsub(/\0/, '')