.dbf is a relational database format introduced in DOS database management system dBASE in 1982.
One .dbf file corresponds to one table and contains a series of headers, specification of fields, and a number of fixed-size records.
This page hosts a formal specification of .dbf file format of dBASE using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.
// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.
import (
"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
"bytes"
)
/**
* .dbf is a relational database format introduced in DOS database
* management system dBASE in 1982.
*
* One .dbf file corresponds to one table and contains a series of headers,
* specification of fields, and a number of fixed-size records.
* @see <a href="http://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm">Source</a>
*/
type Dbf_DeleteState int
const (
Dbf_DeleteState__False Dbf_DeleteState = 32
Dbf_DeleteState__True Dbf_DeleteState = 42
)
var values_Dbf_DeleteState = map[Dbf_DeleteState]struct{}{32: {}, 42: {}}
func (v Dbf_DeleteState) isDefined() bool {
_, ok := values_Dbf_DeleteState[v]
return ok
}
type Dbf struct {
Header1 *Dbf_Header1
Header2 *Dbf_Header2
HeaderTerminator []byte
Records []*Dbf_Record
_io *kaitai.Stream
_root *Dbf
_parent kaitai.Struct
_raw_Header2 []byte
_raw_Records [][]byte
}
func NewDbf() *Dbf {
return &Dbf{
}
}
func (this Dbf) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf) Read(io *kaitai.Stream, parent kaitai.Struct, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp1 := NewDbf_Header1()
err = tmp1.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Header1 = tmp1
tmp2, err := this._io.ReadBytes(int((this.Header1.LenHeader - 12) - 1))
if err != nil {
return err
}
tmp2 = tmp2
this._raw_Header2 = tmp2
_io__raw_Header2 := kaitai.NewStream(bytes.NewReader(this._raw_Header2))
tmp3 := NewDbf_Header2()
err = tmp3.Read(_io__raw_Header2, this, this._root)
if err != nil {
return err
}
this.Header2 = tmp3
tmp4, err := this._io.ReadBytes(int(1))
if err != nil {
return err
}
tmp4 = tmp4
this.HeaderTerminator = tmp4
if !(bytes.Equal(this.HeaderTerminator, []uint8{13})) {
return kaitai.NewValidationNotEqualError([]uint8{13}, this.HeaderTerminator, this._io, "/seq/2")
}
for i := 0; i < int(this.Header1.NumRecords); i++ {
_ = i
tmp5, err := this._io.ReadBytes(int(this.Header1.LenRecord))
if err != nil {
return err
}
tmp5 = tmp5
this._raw_Records = append(this._raw_Records, tmp5)
_io__raw_Records := kaitai.NewStream(bytes.NewReader(this._raw_Records[i]))
tmp6 := NewDbf_Record()
err = tmp6.Read(_io__raw_Records, this, this._root)
if err != nil {
return err
}
this.Records = append(this.Records, tmp6)
}
return err
}
type Dbf_Field struct {
Name string
Datatype uint8
DataAddress uint32
Length uint8
DecimalCount uint8
Reserved1 []byte
WorkAreaId uint8
Reserved2 []byte
SetFieldsFlag uint8
Reserved3 []byte
_io *kaitai.Stream
_root *Dbf
_parent *Dbf_Header2
}
func NewDbf_Field() *Dbf_Field {
return &Dbf_Field{
}
}
func (this Dbf_Field) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf_Field) Read(io *kaitai.Stream, parent *Dbf_Header2, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp7, err := this._io.ReadBytes(int(11))
if err != nil {
return err
}
tmp7 = kaitai.BytesTerminate(tmp7, 0, false)
this.Name = string(tmp7)
tmp8, err := this._io.ReadU1()
if err != nil {
return err
}
this.Datatype = tmp8
tmp9, err := this._io.ReadU4le()
if err != nil {
return err
}
this.DataAddress = uint32(tmp9)
tmp10, err := this._io.ReadU1()
if err != nil {
return err
}
this.Length = tmp10
tmp11, err := this._io.ReadU1()
if err != nil {
return err
}
this.DecimalCount = tmp11
tmp12, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp12 = tmp12
this.Reserved1 = tmp12
tmp13, err := this._io.ReadU1()
if err != nil {
return err
}
this.WorkAreaId = tmp13
tmp14, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp14 = tmp14
this.Reserved2 = tmp14
tmp15, err := this._io.ReadU1()
if err != nil {
return err
}
this.SetFieldsFlag = tmp15
tmp16, err := this._io.ReadBytes(int(8))
if err != nil {
return err
}
tmp16 = tmp16
this.Reserved3 = tmp16
return err
}
/**
* @see <a href="http://www.dbase.com/Knowledgebase/INT/db7_file_fmt.htm">- section 1.1</a>
*/
type Dbf_Header1 struct {
Version uint8
LastUpdateY uint8
LastUpdateM uint8
LastUpdateD uint8
NumRecords uint32
LenHeader uint16
LenRecord uint16
_io *kaitai.Stream
_root *Dbf
_parent *Dbf
_f_dbaseLevel bool
dbaseLevel int
}
func NewDbf_Header1() *Dbf_Header1 {
return &Dbf_Header1{
}
}
func (this Dbf_Header1) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf_Header1) Read(io *kaitai.Stream, parent *Dbf, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp17, err := this._io.ReadU1()
if err != nil {
return err
}
this.Version = tmp17
tmp18, err := this._io.ReadU1()
if err != nil {
return err
}
this.LastUpdateY = tmp18
tmp19, err := this._io.ReadU1()
if err != nil {
return err
}
this.LastUpdateM = tmp19
tmp20, err := this._io.ReadU1()
if err != nil {
return err
}
this.LastUpdateD = tmp20
tmp21, err := this._io.ReadU4le()
if err != nil {
return err
}
this.NumRecords = uint32(tmp21)
tmp22, err := this._io.ReadU2le()
if err != nil {
return err
}
this.LenHeader = uint16(tmp22)
tmp23, err := this._io.ReadU2le()
if err != nil {
return err
}
this.LenRecord = uint16(tmp23)
return err
}
func (this *Dbf_Header1) DbaseLevel() (v int, err error) {
if (this._f_dbaseLevel) {
return this.dbaseLevel, nil
}
this._f_dbaseLevel = true
this.dbaseLevel = int(this.Version & 7)
return this.dbaseLevel, nil
}
type Dbf_Header2 struct {
HeaderDbase3 *Dbf_HeaderDbase3
HeaderDbase7 *Dbf_HeaderDbase7
Fields []*Dbf_Field
_io *kaitai.Stream
_root *Dbf
_parent *Dbf
}
func NewDbf_Header2() *Dbf_Header2 {
return &Dbf_Header2{
}
}
func (this Dbf_Header2) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf_Header2) Read(io *kaitai.Stream, parent *Dbf, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp24, err := this._root.Header1.DbaseLevel()
if err != nil {
return err
}
if (tmp24 == 3) {
tmp25 := NewDbf_HeaderDbase3()
err = tmp25.Read(this._io, this, this._root)
if err != nil {
return err
}
this.HeaderDbase3 = tmp25
}
tmp26, err := this._root.Header1.DbaseLevel()
if err != nil {
return err
}
if (tmp26 == 7) {
tmp27 := NewDbf_HeaderDbase7()
err = tmp27.Read(this._io, this, this._root)
if err != nil {
return err
}
this.HeaderDbase7 = tmp27
}
for i := 0;; i++ {
tmp28, err := this._io.EOF()
if err != nil {
return err
}
if tmp28 {
break
}
tmp29 := NewDbf_Field()
err = tmp29.Read(this._io, this, this._root)
if err != nil {
return err
}
this.Fields = append(this.Fields, tmp29)
}
return err
}
type Dbf_HeaderDbase3 struct {
Reserved1 []byte
Reserved2 []byte
Reserved3 []byte
_io *kaitai.Stream
_root *Dbf
_parent *Dbf_Header2
}
func NewDbf_HeaderDbase3() *Dbf_HeaderDbase3 {
return &Dbf_HeaderDbase3{
}
}
func (this Dbf_HeaderDbase3) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf_HeaderDbase3) Read(io *kaitai.Stream, parent *Dbf_Header2, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp30, err := this._io.ReadBytes(int(3))
if err != nil {
return err
}
tmp30 = tmp30
this.Reserved1 = tmp30
tmp31, err := this._io.ReadBytes(int(13))
if err != nil {
return err
}
tmp31 = tmp31
this.Reserved2 = tmp31
tmp32, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp32 = tmp32
this.Reserved3 = tmp32
return err
}
type Dbf_HeaderDbase7 struct {
Reserved1 []byte
HasIncompleteTransaction uint8
DbaseIvEncryption uint8
Reserved2 []byte
ProductionMdx uint8
LanguageDriverId uint8
Reserved3 []byte
LanguageDriverName []byte
Reserved4 []byte
_io *kaitai.Stream
_root *Dbf
_parent *Dbf_Header2
}
func NewDbf_HeaderDbase7() *Dbf_HeaderDbase7 {
return &Dbf_HeaderDbase7{
}
}
func (this Dbf_HeaderDbase7) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf_HeaderDbase7) Read(io *kaitai.Stream, parent *Dbf_Header2, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp33, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp33 = tmp33
this.Reserved1 = tmp33
if !(bytes.Equal(this.Reserved1, []uint8{0, 0})) {
return kaitai.NewValidationNotEqualError([]uint8{0, 0}, this.Reserved1, this._io, "/types/header_dbase_7/seq/0")
}
tmp34, err := this._io.ReadU1()
if err != nil {
return err
}
this.HasIncompleteTransaction = tmp34
tmp35, err := this._io.ReadU1()
if err != nil {
return err
}
this.DbaseIvEncryption = tmp35
tmp36, err := this._io.ReadBytes(int(12))
if err != nil {
return err
}
tmp36 = tmp36
this.Reserved2 = tmp36
tmp37, err := this._io.ReadU1()
if err != nil {
return err
}
this.ProductionMdx = tmp37
tmp38, err := this._io.ReadU1()
if err != nil {
return err
}
this.LanguageDriverId = tmp38
tmp39, err := this._io.ReadBytes(int(2))
if err != nil {
return err
}
tmp39 = tmp39
this.Reserved3 = tmp39
if !(bytes.Equal(this.Reserved3, []uint8{0, 0})) {
return kaitai.NewValidationNotEqualError([]uint8{0, 0}, this.Reserved3, this._io, "/types/header_dbase_7/seq/6")
}
tmp40, err := this._io.ReadBytes(int(32))
if err != nil {
return err
}
tmp40 = tmp40
this.LanguageDriverName = tmp40
tmp41, err := this._io.ReadBytes(int(4))
if err != nil {
return err
}
tmp41 = tmp41
this.Reserved4 = tmp41
return err
}
type Dbf_Record struct {
Deleted Dbf_DeleteState
RecordFields [][]byte
_io *kaitai.Stream
_root *Dbf
_parent *Dbf
}
func NewDbf_Record() *Dbf_Record {
return &Dbf_Record{
}
}
func (this Dbf_Record) IO_() *kaitai.Stream {
return this._io
}
func (this *Dbf_Record) Read(io *kaitai.Stream, parent *Dbf, root *Dbf) (err error) {
this._io = io
this._parent = parent
this._root = root
tmp42, err := this._io.ReadU1()
if err != nil {
return err
}
this.Deleted = Dbf_DeleteState(tmp42)
for i := 0; i < int(len(this._root.Header2.Fields)); i++ {
_ = i
tmp43, err := this._io.ReadBytes(int(this._root.Header2.Fields[i].Length))
if err != nil {
return err
}
tmp43 = tmp43
this.RecordFields = append(this.RecordFields, tmp43)
}
return err
}