DBASE
dBase Format

A dBase File has a prefix, a header and rows of data.




Prefix
- id (byte)
- year (byte)
- month (byte)
- day (byte)
- Number of records (UInt32)
- headersite (Uint16)
- RecordSize (Uint16)
- 20 fillbytes





Byte/Offset Number of Bytes Description
0 1 dBase Version, Valid dBASE for Windows table file, bits 0-2 indicate version number: 3 for dBASE Level 5, 4 for dBASE Level 7.

Bit 3 and bit 7 indicate presence of a dBASE IV or dBASE for Windows memo file; bits 4-6 indicate the presence of a dBASE IV SQL table; bit 7 indicates the presence of any .DBT memo file (either a dBASE III PLUS type or a dBASE IV or dBASE for Windows memo file).
1-3 3 YY / MM / DD
4-7 unsgined 32 Bit Number of records
8-9 unsgined 16 Bit Number of bytes in the header
10-11 unsgined 16 Bit Number of bytes in the records
12-13 2 reserved
14 1 Flag indicating incomplete dBASE IV transaction.
15 1 dBASE IV encryption flag.
16-27 12 reserved
28 1 Production MDX flag; 0x01 if a production .MDX file exists for this table; 0x00 if no .MDX file exists.
29 1 Language driver ID
30-31 2 Reserved
32-63 32 Language driver name
64-67 4 Reserved
68-n 48 Byte each Field descriptor
n+1 1 Field descriptor terminator
n+2    



Field descriptor

Byte/Offset Number of Bytes Description
0-31 32 Fieldname (zero-filled)
read only until byte-value are zero
32 1 Field type in ASCII (B, C, D, N, L, M, @, I, +, F, 0 or G).
B: blog
C: Chars
D: Date
N: Numeric
L: Logical, boolean
I: Integer
35-36 2 reserved
37 1 Production .MDX field flag; 0x01 if field has an index tag in the production .MDX file; 0x00 if the field is not indexed.
38-39 2 reserved
40-43 4 Next Autoincrement value, if the Field type is Autoincrement, 0x00 otherwise.
44-47 4 reserved



Source classes (C#)
class Dbheader3 {
   public byte id;        // 2=dbase2    3=dbase3    131=dBase3 mit Memofeld
   public byte jahr;      // datum
   public byte monat;
   public byte tag;
   public UInt32 anzrec;       // Anzahl der Datensaetze */
   public UInt16 headersize;      // Headergroesse in Byte */
   public UInt16 recsize;           // Laenge eines einzelnen Datensatzes
   public byte[] dummy;
}


class Field {
   public String fieldname;  // 11 Zeichen
   public char typ;      //  C=String; N=Zahl; D=Datum; L=Boolean  M=Memotext
   public UInt32 fieldadr;       // Anzahl der Datensaetze */
   public byte size;
   public byte nk;
   // 14 dummys
   public UInt16 offset;
}

class Row {
  private static byte[] dummy = new byte[255];
  public List attribs = new List();
}



Source methods of the classes (C#)
class Dbheader3 {
   public byte id;        // 2=dbase2    3=dbase3    131=dBase3 mit Memofeld
   public byte jahr;      // datum
   public byte monat;
   public byte tag;
   public UInt32 anzrec;       // Anzahl der Datensaetze */
   public UInt16 headersize;      // Headergroesse in Byte */
   public UInt16 recsize;           // Laenge eines einzelnen Datensatzes
   public byte[] dummy;
}


class Field {
   public String fieldname;  // 11 Zeichen
   public char typ;      //  C=String; N=Zahl; D=Datum; L=Boolean  M=Memotext
   public UInt32 fieldadr;       // Anzahl der Datensaetze */
   public byte size;
   public byte nk;
   // 14 dummys
   public UInt16 offset;
}

class Row {
public void loadRow(BinaryReader inStream, List fieldlist)   {
   String strValue;
   Decimal decValue;
   int intValue;
   foreach (Field_rec fieldrec in fieldlist) {
      switch (fieldrec.typ) {
         case 'C':       // read size bytes
            dummy = inStream.ReadBytes(fieldrec.size);
            sb.Clear();
            for (int i = 0; i < fieldrec.size; i++) {
               sb.Append(((char)dummy[i]).ToString());
            }
            strValue = sb.ToString();
            attribs.Add(strValue.Trim().Clone());
            break;
         case 'I':       // read size bytes Integer
            dummy = inStream.ReadBytes(fieldrec.size);
            sb.Clear();
            for (int i = 0; i < fieldrec.size; i++) {
               sb.Append(((char)dummy[i]).ToString());
            }
            strValue = sb.ToString();
            if (int.TryParse(strValue, out intValue))
               attribs.Add(intValue);
            else
               attribs.Add(0);
            break;
         case 'F':
            // n nk         10/4        12345.1234
            dummy = inStream.ReadBytes(fieldrec.size);
            sb.Clear();
            for (int i = 0; i < fieldrec.size; i++) {
               sb.Append(((char)dummy[i]).ToString());
            }
            strValue = sb.ToString().Trim();
            if (Decimal.TryParse(strValue,
               System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign,
               System.Globalization.CultureInfo.InvariantCulture, out decValue))
               attribs.Add(decValue);
            else
               attribs.Add(0.0);
            break;
         case 'L':
            dummy = inStream.ReadBytes(fieldrec.size);
            if (dummy.Equals("T") || dummy.Equals("True") || dummy.Equals("Wahr"))
               attribs.Add(true);
            else
               attribs.Add(true);
            break;
         case 'D':
            dummy = inStream.ReadBytes(fieldrec.size);
            sb.Clear();
            for (int i = 0; i < fieldrec.size; i++) {
               sb.Append(((char)dummy[i]).ToString());
            }
            strValue = sb.ToString();
            attribs.Add(strValue.Clone());
            break;
         case 'M':
            break;
      }  // switch
   }
}
}


Start the programm

public String readdBaseFile2String(String filename)  {
      const byte eof = 26;
      const byte rowIsDelete = 42; // *
      StringBuilder sb = new StringBuilder();
      List tabelle = new List();
      FileStream inFile = null;
      BinaryReader inStream = null;
      try {
        Dbheader3 header = new Dbheader3();
        inFile = new FileStream(filename, FileMode.Open);
        inStream = new BinaryReader(inFile);

        header.load1(inStream);
        sb.AppendLine("Header: ");
        sb.AppendLine(header.ToString());

        // Felder bestimmen
        List fieldlist = new List();
        Field_rec field;
        while (true) {
          field = new Field_rec();
          field.load(inStream);
          String name = field.fieldname;
          fieldlist.Add(field);
          long position = inFile.Position;
          // Preview für 
          byte eoffield = inStream.ReadByte();
          if (eoffield == 13) {
            break;
          }
          else {
            inFile.Seek(position, SeekOrigin.Begin);
          }
        }
        sb.AppendLine();
        sb.AppendLine("Felder");
        foreach (Field_rec fieldloop in fieldlist) {
          sb.AppendLine(fieldloop.ToString());
        }
        byte flag;
        Row row;
        // vor jedem Datensatz steht das "Deleteflag  20=okay  46=gelöscht
        while (true) {
          flag = inStream.ReadByte();  // space oder *  oder 1A
          if (flag == eof) {
            break;
          } // if (flag!=eof) {
          row = new Row();
          row.loadRow(inStream, fieldlist);
          if (flag != rowIsDelete) {
            tabelle.Add(row);
          }
          // 
        } // while 

        int anzDatensaetze = tabelle.Count;
        sb.AppendLine("anzDatensaetze:" + anzDatensaetze);

        foreach (Row rowloop in tabelle) {
          rowloop.printFields(sb);
        }

        inStream.Close();
        inFile.Close();
      }
      catch (Exception e) {
        sb.AppendLine("Fehler beim Öffnen der Datei:");
        sb.Append(" ");
        sb.AppendLine(filename);
        sb.AppendLine("Fehlermeldung:");
        sb.Append(" ");
        sb.AppendLine(e.ToString());
        inStream.Close();
        inFile.Close();
      }
      return sb.ToString();

    }


Links

description: dBase.pdf
dBase-Files: dbf-files.zip
sales.dbf with a hexviewer: sales.txt

samples programm in c#
dBase.zip (only the program)
dBase.exe (only the program)
dBase-source.zip
dbase.jpg