Formato do Arquivo DBF


  A seguir será apresentado o formato do arquivo .DBF, que é o arquivo de banco de dados criado pelo DBASE II. Esse arquivo contém tanto a estrutura de dados da tabela (campos), como os dados da tabela (registros) [1].

  Tabela 1: Descrição do arquivo .DBF.
Offset
(hexa)
Tamanho
(bytes)
Descrição
0000 1 Versão do DBASE. &H02 = DBASE II.
0001 2 Número de registros no arquivo.
0003 1 Dia da última atualização.
0004 1 Mês da última atualização.
0005 1 Ano da última atualização.
0006 2 Tamanho em bytes de cada registro.
0008 32 x 16 32 Registros contendo descritores de campos, com 16 bytes cada.
Vide tabela 2.
0208 1 Se &H0D, todos os descritores de campo foram utilizados, senão &H00.
0209 n Área de dados dos registros. Formato texto.


  Tabela 2: formato do registro de descritores de campo.
Offset
(hexa)
Tamanho
(bytes)
Descrição
0000 11 Nome do campo. Se o primeiro caractere for "&H0D", marca o fim dos descritores.
0011 1 Tipo de dado:
'C' - Carctere
'N' - Numérico
'L' - Lógico
0012 1 Comprimento do campo.
0013 2 Endereço do dado na memória RAM.
0015 1 Número de casas decimais.
  Obs: o offset da tabela 2 é relativo a cada registro, começando pelo endereço &H0008.

  A primeira parte do arquivo é um cabeçalho no formato binário, contendo informações gerais do banco de dados.
  A segunda parte é também no formato binário e contém informações quanto à estrutura da tabela, ou seja, a descrição de no máximo 32 campos possíveis. As informações de cada campo estão em seqüência.
  Por último, é a área de dados toda no formato texto, contendo informação de cada registro em seqüência. É acrescido a cada registro um caractere de espaço em branco. Assim, cada registro passa a ter comprimento igual a tamanho_de_registro + 1.


  Programa para ler arquivos DBF

  O programa escrito na linguagem C a seguir, lê um arquivo .DBF e imprime as informações encontradas. Pode ser compilado tanto no PC, como no MSX. No caso do MSX, substituir os sinais de maior menor do "#include" por aspas. Ex: #include "stdio.h".
/*
 *  Program dbf_print
 * 
 *  Author: Marcelo Silveira
 *  E-mail: flamar98@hotmail.com
 *  Feb, 2017
 */

#include <stdio.h>
#include <string.h>

struct dbf_header_model
{
  unsigned char version;
  unsigned int no_records;
  unsigned char day, month, year;
  unsigned int size_record;

  unsigned char no_structures;

} dbf_header;

struct structure_model
{
  char name[11];
  char data_type;
  char length;
  char decimal;
  int data_addr;
} structure[32];

FILE *fp;
char buffer[1024];

void read_structure()
{
  int i;
  char p = dbf_header.no_structures;
  int offset = 8 + p * 16;

  while (buffer[offset] != 0x0D && p<=32)
  {
    for (i=0; i<11; i++)
      structure[p].name[i] = buffer[offset+i];

    structure[p].data_type = buffer[offset+11];
    structure[p].length = buffer[offset+12];
    structure[p].data_addr = buffer[offset+14]*256 + buffer[offset+13];
    structure[p].decimal = buffer[offset+15];

    offset += 16;
    p++;
  }
  dbf_header.no_structures = p;
}

void read_header()
{
  dbf_header.version = buffer[0];
  dbf_header.no_records = buffer[2]*256 + buffer[1];
  dbf_header.day = buffer[3];
  dbf_header.month = buffer[4];
  dbf_header.year = buffer[5];
  dbf_header.size_record = buffer[7]*256 + buffer[6];

  dbf_header.no_structures = 0;
}

void print_data()
{
  int i, s, r, count;
  int offset = 0x209 + 1;

  printf("** Registers **\n");

  for (i=0; i<dbf_header.no_records; i++)
  {
    s=0; 
    count=0;

    for (r=0; r<dbf_header.size_record-1; r++)
    {
      if (offset+r > 1023)
      {
        fread(buffer, 1024, 1, fp);
        offset=-r;
      }

      count++;
      if (count > structure[s].length)
      {
        printf("  ");
        count=1;
        s++;
      }
      printf("%c", buffer[offset+r]);
      
    }
    printf("\n");
    offset += dbf_header.size_record;
  }
}

void print_structure()
{
  int i=0;

  printf("** Database structure **\n");
  printf("Name, Type, Length, Address in RAM, Decimal\n-------------------------------------------\n");

  for (i=0; i<dbf_header.no_structures; i++)
    printf("%-11s %c %03d %04X %03d\n", structure[i].name, structure[i].data_type, structure[i].length, structure[i].data_addr, structure[i].decimal);

  printf("Total of fields: %d\n\n", dbf_header.no_structures);
}

void print_header()
{
  printf("Header of DBF file\n------------------\n");
  printf("DBASE version: %d\n", dbf_header.version);
  printf("No. Records: %d\n", dbf_header.no_records);
  printf("Day: %d\n", dbf_header.day);
  printf("Month: %d\n", dbf_header.month);
  printf("Year: %d\n", dbf_header.year);
  printf("Size of each record: %d\n\n", dbf_header.size_record);
}

void print_DBF()
{
  printf("DBF File Reader\n\n"); 
  read_header();
  print_header();
  read_structure();
  print_structure();
  print_data();
  printf("\nMarMSX 2017\n");
}

void help()
{
  printf("** Leitor de arquivos .DBF **\nMarMSX 2017\nUso: dbf_print \nEx: dbf_print myfile.dbf\n");
}

int main(int argc, char* args[])
{
  if (argc == 2)
  {
    if (fp = fopen(args[1],"rb"))
    {
      fread(buffer, 1024, 1, fp);
      print_DBF();
      fclose(fp);
    }
    else
      printf("File %s not found!\n", args[1]);
  }
  else
    help();
}



  Referências:

  [1]- http://www.fileformat.info/format/dbf/corion-dbase-ii.htm


/MARMSX/CURSOS/DBASEII