lib/dbf/table.rb in dbf-4.1.3 vs lib/dbf/table.rb in dbf-4.1.4
- old
+ new
@@ -10,11 +10,12 @@
class Table
extend Forwardable
include Enumerable
include ::DBF::Schema
- DBF_HEADER_SIZE = 32
+ DBASE2_HEADER_SIZE = 8
+ DBASE3_HEADER_SIZE = 32
VERSIONS = {
'02' => 'FoxBase',
'03' => 'dBase III without memo file',
'04' => 'dBase IV without memo file',
@@ -65,13 +66,13 @@
#
# # working with a dbf overriding specified in the dbf encoding
# table = DBF::Table.new 'data.dbf', nil, 'cp437'
# table = DBF::Table.new 'data.dbf', 'memo.dbt', Encoding::US_ASCII
#
- # @param [String, StringIO] data Path to the dbf file or a StringIO object
- # @param [optional String, StringIO] memo Path to the memo file or a StringIO object
- # @param [optional String, Encoding] encoding Name of the encoding or an Encoding object
+ # @param data [String, StringIO] data Path to the dbf file or a StringIO object
+ # @param memo [optional String, StringIO] memo Path to the memo file or a StringIO object
+ # @param encoding [optional String, Encoding] encoding Name of the encoding or an Encoding object
def initialize(data, memo = nil, encoding = nil)
@data = open_data(data)
@encoding = encoding || header.encoding
@memo = open_memo(data, memo)
yield self if block_given?
@@ -96,11 +97,11 @@
# Column names
#
# @return [String]
def column_names
- columns.map(&:name)
+ @column_names ||= columns.map(&:name)
end
# All columns
#
# @return [Array]
@@ -143,12 +144,12 @@
# matched exactly with the value in the database. If you specify more
# than one key, all values must match in order for the record to be
# returned. The equivalent SQL would be "WHERE key1 = 'value1'
# AND key2 = 'value2'".
#
- # @param [Integer, Symbol] command
- # @param [optional, Hash] options Hash of search parameters
+ # @param command [Integer, Symbol] command
+ # @param options [optional, Hash] options Hash of search parameters
# @yield [optional, DBF::Record, NilClass]
def find(command, options = {}, &block)
case command
when Integer
record(command)
@@ -209,20 +210,33 @@
private
def build_columns # :nodoc:
safe_seek do
- @data.seek(DBF_HEADER_SIZE)
+ @data.seek(header_size)
[].tap do |columns|
until end_of_record?
- column_data = @data.read(DBF_HEADER_SIZE)
- columns << Column.new(self, *column_data.unpack('a10 x a x4 C2'))
+ case version
+ when '02'
+ column_data = @data.read(header_size * 2)
+ columns << Column.new(self, *column_data.unpack('A11 a C'), 0)
+ else
+ column_data = @data.read(header_size)
+ columns << Column.new(self, *column_data.unpack('A11 a x4 C2'))
+ end
end
end
end
end
+ def header_size
+ header_size = case version
+ when '02' then DBASE2_HEADER_SIZE
+ else DBASE3_HEADER_SIZE
+ end
+ end
+
def deleted_record? # :nodoc:
flag = @data.read(1)
flag ? flag.unpack1('a') == '*' : true
end
@@ -248,10 +262,10 @@
end
def header # :nodoc:
@header ||= safe_seek do
@data.seek(0)
- Header.new(@data.read(DBF_HEADER_SIZE))
+ Header.new(@data.read(DBASE3_HEADER_SIZE))
end
end
def memo_class # :nodoc:
@memo_class ||= begin