DBF::Table.newaccepts any IO-like object responding to#readand#seek(File,Tempfile, …) in addition to a path orStringIO, matching what the README already documented; IO inputs are switched to binary mode, and memo auto-discovery works from the IO's path when it has oneDBF::Errorbase class: all library errors (FileNotFoundError,NoColumnsDefined,Column::LengthError,Column::InvalidNameError) now inherit from it, so callers canrescue DBF::Errorto catch anything the library raisesTable#filenamenow works for any IO input with a path, not onlyFileDBF::Table.open: same arguments as.new, but the block form yields the table, closes it when the block returns, and returns the block's value — the same contract asFile.open- CI: lint job running RuboCop and Reek on every push and pull request
- CI: test on Windows and macOS (Ruby 3.4) in addition to Linux, since much real-world DBF data originates on Windows/FoxPro systems
- CI: observe-only (non-blocking) test jobs for JRuby, TruffleRuby, and Ruby head
- CI: enforce a 99% minimum test coverage floor via SimpleCov
- Docs site (dbf.infused.org): YARD docs are now built and deployed by CI instead of being committed to the repository; the Pages workflow's deprecated v2/v3 actions (whose artifact backend was shut down in early 2025) are updated to current versions, repairing the broken deploy
- Dependabot updates for GitHub Actions and gems (weekly), a security policy (SECURITY.md) with private vulnerability reporting, and contributor documentation (CONTRIBUTING.md)
- Automated releases: pushing a
vX.Y.Ztag now builds and publishes the gem to RubyGems.org from CI via Trusted Publishing (OIDC) — no long-lived API key.bundler/gem_tasksis loaded in the Rakefile, providingrake build/rake release. Git tags resume at v5.4.0; versions 4.0.0–5.3.0 were released without tags - Ractor safety: all library constants are verified Ractor-shareable and reading/exporting tables inside non-main Ractors is covered by specs
- CLI:
-jexports records as a JSON array and-Jas JSON Lines (one record per line, streamed in constant memory); deleted records are skipped, control bytes are escaped by JSON itself, and binary cells are scrubbed instead of raising
Table#to_csv(path)closes the file it opens, so the CSV is fully flushed to disk when the method returns (previously the data could stay buffered until garbage collection)- Visual FoxPro: a
.dbccontainer supplying fewer long names than the table has columns no longer crashes column building; missing long names fall back to the table's own column names. Column rebuilding is also no longer O(n²) Table#schemavalidates the format against the documented list up front; aNoMethodErrorraised inside a valid schema generator is no longer misreported as "not a valid schema"- FoxPro memo files shorter than their 512-byte header no longer crash memo reads (they return nil like other truncations)
- RuboCop config: restore the default
vendor/**/*exclusion (overridingExcludereplaces the defaults), fixing a CI lint crash where RuboCop descended into cached vendored gems and tried to load plugins from their configs - CLI: close the table when finished, so the DBF file can be deleted or replaced immediately afterwards on Windows (an open handle blocks deletion there)
- CodeClimate config and README badges: the service is sunset, and coverage is now enforced directly in CI
- Streaming reads:
Table#eachnow reads records in 4 MB chunks of whole records instead of loading the entire record section into memory, so enumerating multi-gigabyte files (for example shapefile.dbfsidecars) uses bounded memory. On a 190 MB file, peak process memory drops from ~222 MB to ~35 MB with identical results. No API change; all malformed-file bounds are preserved - Internal:
DBF::RecordContextis now an immutableDataclass instead of aStruct - Internal: remove a redundant
Memo::Foxpro#initializeand the duplicateHeader::HEADER_SIZEconstant (now sourced fromVersionConfig) - README: replace the stack of version-support notes with a compatibility table, point API docs at dbf.infused.org, and refer to LICENSE instead of inlining the full MIT text; copyright years updated through 2026
- Gemspec: add
homepage_uri,bug_tracker_uri,documentation_uri, andfunding_urimetadata (shown on the rubygems.org sidebar), and constrain thecsvruntime dependency to~> 3.3 DBF::Column::NameErroris renamed toDBF::Column::InvalidNameError(it shadowed Ruby's::NameErrorwithout being one); the old constant remains as a deprecated alias- Rescues in date/datetime decoding and FoxPro memo reads are narrowed to the specific expected errors, so genuine programmer errors surface instead of silently returning nil
- Declare
reekandsimplecovas direct development dependencies instead of relying on rubycritic's transitive dependencies - Restrict
debugandruby-lspto MRI sobundle installsucceeds on JRuby/TruffleRuby - Test matrix no longer fails fast, and a Ruby head regression no longer fails the build
- Update pinned
ruby/setup-rubyaction to v1.321.0
- CLI: replace terminal control bytes in file-derived output so a crafted DBF cannot emit escape sequences to an interactive terminal; CSV and schema output are only filtered when writing to a terminal, so redirected exports are unchanged
- Security (CWE-248): write binary or invalidly encoded cells in
Table#to_csvas representable text instead of raising an encoding error - Security (CWE-248): replace unrepresentable column type bytes so a corrupt descriptor cannot raise when the schema is serialized to JSON
- Security (CWE-248):
Table#recordreturns nil when the file ends after the delete flag instead of crashing on a nil record body - Security (CWE-248): stop column parsing when the file ends mid-descriptor instead of raising
ArgumentErrorfrom a short unpack - Security (CWE-248): guard FoxPro memo-pointer decoding against a nil value from a truncated record instead of crashing on nil.unpack1
- Security (CWE-248): guard dBase IV memo reads against a nil/short block header instead of crashing on nil.unpack1
- Security (CWE-248): guard dBase III memo reads against a start block past EOF instead of crashing on a nil block
- Security (CWE-248): stop column parsing on a truncated descriptor instead of constructing an invalid column that crashes on a nil length
- Security (CWE-248): decode truncated numeric cells (Currency, AutoIncrement) to blank instead of raising an uncaught
nilcrash - Security (CWE-248): handle truncated headers and missing column terminators gracefully instead of raising an uncaught
nilcrash during column parsing - Security (CWE-400): bound FoxPro memo reads by the memo file size so a crafted memo size cannot force a ~4 GiB allocation
- Security (CWE-400): bound dBase IV memo reads by the memo file size so a crafted length field cannot force a ~4 GiB allocation
- Security (CWE-835): bound record iteration by the bytes actually read so a crafted
record_count(or zerorecord_length) cannot cause an unbounded loop - Security (CWE-789): bound the record read buffer by the file's actual size so a crafted header cannot force a multi-gigabyte allocation from a tiny file
- Security (CWE-400): resolve FoxPro
.dbctables by scanning the directory instead ofDir.glob, preventing glob brace-expansion CPU exhaustion from a crafted object name - Security (CWE-22): confine Visual FoxPro
.dbctable resolution to the database directory, preventing path traversal via a crafted container object name - Security (CWE-1236): neutralize spreadsheet formula injection in
Table#to_csvby prefixing a quote to string cells/headers starting with= + - @ - Security (CWE-94): escape table and column names when generating ActiveRecord/Sequel schemas, preventing Ruby code injection from crafted DBF header names
- Add support for 8 more code pages (issue #98): Mazovia cp620 and Kamenický cp895 via vendored translation tables (new DBF::Encoder), plus macRoman, cp1255, cp1256, macCyrillic, macCentEuro and macGreek
- Blank Visual FoxPro "T" (DateTime) columns now return nil instead of a Julian day-0 date
- Blank "F" (Float) columns now return nil instead of 0.0, matching "N" (Number) behavior
- Extract CLI logic into DBF::CLI class (bin/dbf is now a thin shim)
- DBF::Table#to_csv now accepts an IO in addition to a String path
- Fix broken link in README
- Drop support for Ruby 3.1 and 3.2
- Frozen string literals
- Drop support for Ruby 3.0.x
- Raise ArgumentError data is not a string or StringIO object
- Refactor the Column class to support non-ASCII header names
- Output encoding is now set to UTF-8 if there is no embedded encoding and one is not specified during DBF::Table initialization.
- Fixes to maintain support for Ruby 3.0.x until it's EOL
- Fix bug (since 4.2.0) that caused column names not to be truncated after null character
- Drop support for Ruby versions older than 3.0
- Require CSV gem
- Exclude unnecessary files from the gem file list
- Require MFA to publish gem
- Faster CSV generation
- Support for dBase IV "04" type files
- Initial support for dBase 7 files
- Add support for file type 32
- Better handling for PIPE errors when using command line utility
- Add full support for FoxBase files
- Raise DBF::NoColumnsDefined error when attempting to read records if no columns are defined
- Add required_ruby_version to gemspec
- Return Time instead of DateTime
- Drop support for ruby-2.2 and earlier
- Ensure malformed dates return nil
- Fix incorrect columns list when StringIO and encoding set
- Use Date.strptime to parse date fields
- Use :binary for binary fields in ActiveRecord schemas
- Fix uninitialized constant error under Rails 5
- Ignore non-existent records if header record count is incorrect
- This version has been yanked from rubygems due to errors
- Override table name for schema output
- Adds -v command-line option to print version
- Adds -r command-line option to create Sequel migration
- Uninitialized (N)umbers should return nil
- Performance improvements for large files
- Support FoxPro (G) general field type
- Fix ruby warnings
- Requires Ruby version 2.0 and above
- Support the (G) General Foxpro field type
- Support 64-bit currency signed currency values (see #71)
- Parse (I) values as signed (see #70)
- Foxpro doubles should always return the full stored precision (see #69)
- allow 0 length fields, but always return nil as value
- fix dBase IV attributes when memo file is missing
- fix FoxPro currency fields on some builds of Ruby 1.9.3 and 2.0.0
- fix the dbf binary on some linux systems
- build_memo returns nil on errors
- use correct FoxPro memo block size
- memo fields return nil if memo file is missing
- set encoding if table encoding is nil
- Allow overriding the character encoding specified in the file
- Add experimental support for character encodings under Ruby 1.8
- #44 Require FasterCSV gem on all platforms
- Remove rdoc development dependency
- #42 Fixes encoding of memos
- #43 Improve handling of record attributes
- fixes FoxPro currency (Y) fields
- Replace Memo Type with Memo File boolean in command-line utility summary output
- find_all/find_first should ignore deleted records
- Fix integer division under Ruby 1.8 when requiring mathn standard library (see http://bugs.ruby-lang.org/issues/2121)
- Fix Table.FOXPRO_VERSIONS breakage on Ruby 1.8
- allow DBF::Table to work with dbf data in memory
- allow DBF::Table#to_csv to write to STDOUT
- memo columns return nil when no memo file found
- add binary data type support to ActiveRecord schema output
- support for visual foxpro double (b) data type
- Replace invalid chars with 'unicode replacement character' (U+FFFD)
- add Table#filename method
- Rakefile now loads gems with bundler
- add Table#supports_encoding?
- simplify encodings.yml loader
- add rake and rdoc as development dependencies
- simplify open_memo file search logic
- remove unnecessary requires in spec helper
- fix cli summary
- fix YAML issue when using MRI version > 1.9.1
- remove Table#seek_to_index and Table#current_record private methods
- remove activesupport gem dependency
- Significant internal restructuring and performance improvements. Initial testing shows 4x faster performance.
- Only load what's needed from activesupport 3.0
- Updatate fastercsv dependency to 1.5.3
- Remove use of 'returning' method
- Remove jeweler in favor of manual gemspec creation
- Move Table#all_values_match? to Record#match?
- Add attr_reader for Record#table
- Use method_defined? instead of respond_to? when defining attribute accessors
- Move memo file check into get_memo_header_info
- Remove unnecessary seek_to_record in Table#each
- Add rake console task
- New Attribute class
- Add a helper method for memo column type
- Move constants into the classes where they are used
- Use bundler
- Retain trailing whitespace in memos
- Handle missing zeros in date values [#11]
- MIT License
- Support for Ruby 1.9.2
- Remove ruby warning switch
- Requires activesupport version 2.3.5
- Add csv output option to dbf command-line utility
- Read Visual FoxPro memos
- Small performance gain when unpacking values from the dbf file
- Correctly handle FoxPro's integer data type
- Handle invalid date fields
- Add support for F field type (Float)
- Add Table#to_a
- Return invalid DateTime columns as nil
- Add support for large table that will not fit into memory
- Allow passing an array of ids to find
- Attributes are now accessible by original or underscored name
- Fix incorrect integer column values (only affecting some dbf files)
- Add CSV export
- Truncate column names on NULL
- Fix schema dump for date and datetime columns
- Replace internal helpers with ActiveSupport
- Always underscore attribute names
- Remove support for original column names. All columns names are now downcased/underscored.
- DBF::Table now includes the Enumerable module
- Return nil for memo values if the memo file is missing
- Finder conditions now support the original and downcased/underscored column names
- Strip non-ascii characters from column names
- Underscore column names when dumping schemas (FieldId becomes field_id)
- Add support for Visual Foxpro Integer and Datetime columns
- Compatibility fix for Visual Foxpro memo files (ignore negative memo index values)
- Fixes error when using the command-line interface [#11984]
- Renamed classes and refactored code in preparation for adding the ability to save records and create/compact databases.
- The Reader class has been renamed to Table
- Attributes are no longer accessed directly from the record. Use record.attribute['column_name'] instead, or use the new attribute accessors detailed under Basic Usage.
- Ignore deleted records in both memory modes
- Added a standalone dbf utility (try dbf -h for help)
- New find method
- Full compatibility with the two flavors of memo file
- Two modes of operation:
- In memory (default): All records are loaded into memory on the first request. Records are retrieved from memory for all subsequent requests.
- File I/O: All records are retrieved from disk on every request
- Improved documentation and more usage examples