lib/dbf/table.rb in dbf-2.0.5 vs lib/dbf/table.rb in dbf-2.0.6
- old
+ new
@@ -32,12 +32,11 @@
"31" => "Visual FoxPro with AutoIncrement field",
"f5" => "FoxPro with memo file",
"fb" => "FoxPro without memo file"
}
- attr_reader :version # Internal dBase version number
- attr_reader :record_count # Total number of records
+ attr_reader :header
attr_accessor :encoding # Source encoding (for ex. :cp1251)
# Opens a DBF::Table
# Examples:
# # working with a file stored on the filesystem
@@ -59,12 +58,13 @@
# @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
def initialize(data, memo = nil, encoding = nil)
@data = open_data(data)
- @version, @record_count, @header_length, @record_length, @encoding_key, @encoding = get_header_info
- @encoding = encoding if encoding
+ @data.rewind
+ @header = Header.new(@data.read(DBF_HEADER_SIZE), supports_encoding? || supports_iconv?)
+ @encoding = encoding || header.encoding
@memo = open_memo(data, memo)
end
# @return [TrueClass, FalseClass]
def has_memo_file?
@@ -96,28 +96,42 @@
# Calls block once for each record in the table. The record may be nil
# if the record has been marked as deleted.
#
# @yield [nil, DBF::Record]
def each
- @record_count.times {|i| yield record(i)}
+ header.record_count.times {|i| yield record(i)}
end
# Retrieve a record by index number.
# The record will be nil if it has been deleted, but not yet pruned from
# the database.
#
# @param [Fixnum] index
# @return [DBF::Record, NilClass]
def record(index)
- seek(index * @record_length)
+ seek(index * header.record_length)
if !deleted_record?
- DBF::Record.new(@data.read(@record_length), columns, version, @memo)
+ DBF::Record.new(@data.read(header.record_length), columns, version, @memo)
end
end
alias_method :row, :record
+ # Internal dBase version number
+ #
+ # @return [String]
+ def version
+ @version ||= header.version
+ end
+
+ # Total number of records
+ #
+ # @return [Fixnum]
+ def record_count
+ @record_count ||= header.record_count
+ end
+
# Human readable version description
#
# @return [String]
def version_description
VERSIONS[version]
@@ -208,11 +222,11 @@
columns = []
while !["\0", "\r"].include?(first_byte = @data.read(1))
column_data = first_byte + @data.read(31)
name, type, length, decimal = column_data.unpack('a10 x a x4 C2')
if length > 0
- columns << column_class.new(name.strip, type, length, decimal, version, @encoding)
+ columns << column_class.new(name.strip, type, length, decimal, version, encoding)
end
end
columns
end
end
@@ -227,11 +241,11 @@
rescue
false
end
def foxpro?
- FOXPRO_VERSIONS.keys.include? @version
+ FOXPRO_VERSIONS.keys.include? version
end
private
def column_class #nodoc
@@ -240,20 +254,20 @@
def memo_class #nodoc
@memo_class ||= if foxpro?
Memo::Foxpro
else
- if @version == "83"
+ if version == "83"
Memo::Dbase3
else
Memo::Dbase4
end
end
end
def column_count #nodoc
- @column_count ||= ((@header_length - DBF_HEADER_SIZE + 1) / DBF_HEADER_SIZE).to_i
+ @column_count ||= ((header.header_length - DBF_HEADER_SIZE + 1) / DBF_HEADER_SIZE).to_i
end
def open_data(data) #nodoc
data.is_a?(StringIO) ? data : File.open(data, 'rb')
end
@@ -292,22 +306,11 @@
def deleted_record? #nodoc
@data.read(1).unpack('a') == ['*']
end
- def get_header_info #nodoc
- @data.rewind
- version, record_count, header_length, record_length, encoding_key = read_header
- encoding = ENCODINGS[encoding_key] if supports_encoding? || supports_iconv?
- [version, record_count, header_length, record_length, encoding_key, encoding]
- end
-
- def read_header #nodoc
- @data.read(DBF_HEADER_SIZE).unpack("H2 x3 V v2 x17H2")
- end
-
def seek(offset) #nodoc
- @data.seek @header_length + offset
+ @data.seek header.header_length + offset
end
def csv_class #nodoc
@csv_class ||= CSV.const_defined?(:Reader) ? FCSV : CSV
end