[comp.sys.ibm.pc] C source to read dBASE files

twaites@sicom.UUCP (Greg Twaites) (05/29/87)

Here is the C code that allows you to read a DBASE-III file. I verified
that it works under Microsoft C v4.0. Hope it does every thing you need.
I am not sure where it came from, so hopefully I am not violating anyones
copyrights :-). Have fun.

Greg Twaites
SICOM Inc.
!ihnp4!sun!sunburn!sicom!twaites

--------------------------------------------------------------------------
/*
 * These functions are used to read dbase files.
 *
 * These functions are provided by Valour Software as a gift.
 *
 * The program is for test purposes only.  No warranty is expressed nor
 * implied. USE AT YOUR OWN RISK!
 *
 *
 */
 
#include <fcntl.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <malloc.h>
 
typedef  struct dbase_head {
    unsigned char   version;     /*03 for dbIII and 83 for dbIII w/memo file*/
    unsigned char   l_update[3];                    /*yymmdd for last update*/
    unsigned long   count;                       /*number of records in file*/
    unsigned int    header;                           /*length of the header
                                                       *includes the \r at end
                                                       */
    unsigned int    lrecl;                            /*length of a record
                                                       *includes the delete
                                                       *byte
                                                       */
    unsigned char   reserv[20];
    } DBASE_HEAD;
 
typedef struct dbase_fld {
    char    name[11];                                           /*field name*/
    char    type;                                               /*field type*/
#define DB_FLD_CHAR  'C'
#define DB_FLD_NUM   'N'
#define DB_FLD_LOGIC 'L'
#define DB_FLD_MEMO  'M'
#define DB_FLD_DATE  'D'
    /* A-T uses large data model but drop it for now */
    char far        *data_ptr;                         /*pointer into buffer*/
    unsigned char   length;                                   /*field length*/
    unsigned char   dec_point;                         /*field decimal point*/
    unsigned char   fill[14];
    } DBASE_FIELD;
 
typedef struct fld_list {
    struct fld_list *next;
    DBASE_FIELD     *fld;
    char            *data;
    } FLD_LIST;
 
DBASE_HEAD  dbhead={0};
FLD_LIST    *db_fld_root=0;
char        *Buffer;
char        buf_work[255];
int         dbfile;
 
/*------------------------------------------------------------code-------*/
main(argc,argv)
int     argc;
char    *argv[];
{
    if(argc!=2)
        error("Usage is db_dump filename.dbf");
    dbfile=open(argv[1],O_RDONLY);
    if(dbfile==-1)
        error("Unable to open file");
    db3_read_dic();
    db3_print_recs(5);
    printf("\n\n\t\t\tProcessing complete");
    close(dbfile);
    exit(0);
}
 
 
/******************************************************
                                         db3_read_dic()
This function is called with a file name to
read to create a record type to support the
dbase file
******************************************************/
 
db3_read_dic()
{
    int             fields;
    DBASE_FIELD     *fld;
 
    if(dbfile==-1) {
        printf("open failed");
        exit(200);
        }
    read(dbfile,&dbhead,sizeof(DBASE_HEAD));
    if( !(dbhead.version==3 || dbhead.version==0x83) )
        error("\n\aVersion %d not supported",dbhead.version);
 
    printf("update year    %3d\n",dbhead.l_update[0]);
    printf("update mon     %3d\n",dbhead.l_update[1]);
    printf("update day     %3d\n",dbhead.l_update[2]);
    printf("number of recs %3d\n",dbhead.count);
    printf("header length  %3d\n",dbhead.header);
    printf("record length  %3d\n",dbhead.lrecl);
    Buffer=malloc(dbhead.lrecl);
 
    fields=(dbhead.header-1)/32-1;
    printf("\nField Name\tType\tLength\tDecimal Pos\n");
    while(fields--) {
        fld=(DBASE_FIELD *)malloc(sizeof(DBASE_FIELD));
        if(!fld)
            error("\n\aNot enough memory\n");
        read(dbfile,fld,sizeof(DBASE_FIELD));
        printf("%-10s\t  %c\t  %3d\t  %3d\n",fld->name,fld->type,
                                     fld->length,fld->dec_point);
        stack_field(fld);
        }
    read(dbfile,Buffer,1);              /*read the silly little \r character*/
    return;
}
 
/******************************************************
                                        db3_print_recs()
Read records and print the data
******************************************************/
 
db3_print_recs(cnt)
int     cnt;
{
    int     bytes;
 
    while(cnt) {
        bytes=read(dbfile,Buffer,dbhead.lrecl);
        if(bytes!=dbhead.lrecl)
            break;
        if(Buffer[0]!='*') {
            db3_print();
            cnt--;
            }
        }
    return;
}
 
 
/******************************************************
                                          db3_print()
Print a single record
******************************************************/
 
db3_print()
{
    FLD_LIST    *list, *temp;
 
    temp=db_fld_root;
    printf("\n");
    while(temp) {
        memcpy(buf_work,temp->data,temp->fld->length);
        buf_work[temp->fld->length]='\0';
        printf("%-10s=%s\n",temp->fld->name,buf_work);
        temp=temp->next;
        }
    return;
}
 
/******************************************************
                                         stack_field()
Add a field to the linked list of fields
******************************************************/
 
stack_field(fld)
DBASE_FIELD *fld;
{
    FLD_LIST    *list, *temp;
 
    list=(FLD_LIST *)calloc(1,sizeof(FLD_LIST));
    if(!list)
        error("\n\aNot enough memory\n");
    list->fld=fld;
    if(!db_fld_root) {
        list->data=Buffer+1;                            /*skip delete byte*/
        db_fld_root=list;
        return;
        }
    temp=db_fld_root;
    while(temp->next)
        temp=temp->next;
    temp->next=list;
    list->data=temp->data + temp->fld->length;
    return;
}
 
 
/******************************************************
                                            error()
Produce error msg and abort
******************************************************/
 
error(msg)
char    *msg;
{
    printf(msg);
    close(dbfile);
    exit(255);
}