c语言写的*.dbf文件的操作函数库

为什么编写本函数库?
  目前好多电力方面的抄表器由于其RAM内存及FLASH闪存的空间都比较小,没有办法象java那样调用各种基于各种大型数据库的外界jar包进行数据采集工作。为此,dbf这种简单的结构型数据库成为手选。另外,因为抄表器要求的数据格式也比较简单,选用这种结构型的最贴合实际。
  基于以上两点,本人上网搜了些这方面的资料,想down一个.dbf驱动,但水平有限没找着,只好自己编写了。

直接贴代码吧:
1:HT_DBF.H,定义了.dbf的几个数据结构。

 /**************************************************************
  **                     c语言操作dbf文件                      
  **
  ** 目前只支持int--N,char--C                                   
  **************************************************************/

#define MAX_INT_LENTH 20
#define MAX_FLOAT_LENTH 20
#define MAX_CHAR_LENTH 254
/***************************************************************
 * 数据库表中的列声明,包含一些列属性
 ***************************************************************/
typedef struct field
{
 char FIELD_NAME[11];
 char FIELD_TYPE;
 int FIELD_X;
 int FIELD_Y;
 unsigned char FIELD_LENTH;
 unsigned char FIELD_FLOAT_LENTH;
 int index;
 struct field * next;
}DBF_FIELD;

/***************************************************************
 * 数据库表的配置信息,包含 文件开始标志,最后更新日期,记录总数,文件头大小,记录大小,列属性链表
 *                       数据库文件句柄,当前记录
 ***************************************************************/
typedef struct {
 unsigned char BEGIN_FLAG;
 unsigned char LAST_UPPDATE_TIME[3];
 long RECORD_COUNT;
 int HEAD_SIZE;
 int RECORD_SIZE;
 DBF_FIELD *head;
 int DBF_HANDLE;
 long current;
}DBF_CONFIG;

/***************************************************************
 * 数据表中的一条记录
 * 为了通用性,仅用一个 void *指示
 * 其中的具体内容,可以参照DBF_CONFIG中的DBF_FIELD *head进行解析
 ***************************************************************/
typedef struct record
{
 void * value;
}DBF_RECORD;

2:HT_DBF.C,操作函数库

#define __ASM  asm

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <io.h>
#include <dos.h>
#include <share.h>
#include <fcntl.h>
#include <string.h>
#include <mem.h>
#include "../project/ht_dbf.h"

DBF_CONFIG * dbfopen(char *fname,DBF_CONFIG * db_con);
int dbfclose(DBF_CONFIG * con);
int dbfread(DBF_CONFIG * con,DBF_RECORD * record);

int dbfgetFieldByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * return_value);
int dbfgetFieldByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * return_value);
int dbfgetFloatByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * return_value);
int dbfgetFloatByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * return_value);
int dbfgetCharByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * return_value);
int dbfgetCharByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * return_value);

int dbfsetFieldByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * value);
int dbfsetFieldByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * value);
int dbfsetFloatByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * value);
int dbfsetFloatByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * value);
int dbfsetCharByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * value);
int dbfsetCharByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * value);

char *ccstr( char *str);

void dbf_info();

void dbf_info()
{
 char column_name[12];
 DBF_FIELD *cur=NULL;
 DBF_RECORD record;
 float b=0.0;
 float c;
 char *record_value;
 char ret_val[MAX_CHAR_LENTH+1];
 /*打开数据库*/
 DBF_CONFIG *con=dbfopen("..//project//CBDATA.DBF",NULL);
 /*数据库配置信息*/
 printf("BEGIN_FLAG:%d/n",con->BEGIN_FLAG);
 printf("LAST_UPPDATE_TIME:%d",con->LAST_UPPDATE_TIME[0]);
 printf(" - %d",con->LAST_UPPDATE_TIME[1]);
 printf(" - %d/n",con->LAST_UPPDATE_TIME[2]);
 printf("RECORD_COUNT:%d/n",con->RECORD_COUNT);
 printf("HEAD_SIZE:%d/n",con->HEAD_SIZE);
 printf("RECORD_SIZE:%d/n",con->RECORD_SIZE);
 printf("DBF_HANDLE:%d/n",con->DBF_HANDLE);
 printf("current:%d/n",con->current);
 /*列信息*/
 cur=con->head;
 while(cur!=NULL){
  strncpy(column_name,cur->FIELD_NAME,11);
  column_name[11]='/0';
  printf("FIELD-INFO-->NAME:%s,TYPE:%c,X:%d,Y:%d,LENTH:%d,FLOAT_LENTH:%d,index:%d/n",column_name,
   cur->FIELD_TYPE,cur->FIELD_X,cur->FIELD_Y,cur->FIELD_LENTH,cur->FIELD_FLOAT_LENTH,cur->index);
  cur=cur->next;
 }

 /*读取第2条记录*/
 con->current=1;
 dbfread(con,&record);
 record_value=(char *)malloc(con->RECORD_SIZE+1);
 memcpy(record_value,record.value,con->RECORD_SIZE);
 *(record_value+con->RECORD_SIZE)='/0';
 printf(record_value);
 printf("/n");
 dbfgetFloatByName(con,&record,"cs1",&b);
 printf("A:%f/n",b);
 dbfgetFloatByIndex(con,&record,2,&c);
 printf("c:%f/n",c);
 printf("/n");
 dbfgetCharByName(con,&record,"HM",ret_val);
 memset(ret_val,'/0',sizeof(ret_val));
 dbfgetCharByIndex(con,&record,1,ret_val);
 printf("ret_val:%s/n",ret_val);
 printf("/ncurrent:%d/n",con->current);
 /*改写数据库记录*/
 con->current=1;
 b=41.01;
 //dbfsetFieldByIndex(con,&record,7,&b);
 dbfsetFloatByIndex(con,&record,7,&b);
 sprintf(ret_val,"%-254s","01-001-01");
 dbfsetCharByName(con,&record,"bh",ret_val);
 sprintf(ret_val,"%-254s","太平路1号");
 dbfsetCharByName(con,&record,"dz",ret_val);

 /*关闭数据库*/
 dbfclose(con);
 getch();
}
/******************************************/

/******************************************
 * 打开指定文件名的文件,并初始化DBF_CONFIG。
 ******************************************/
DBF_CONFIG * dbfopen(char *fname,DBF_CONFIG * db_con)
{
 unsigned tmp,field_x;
 int fhandle;
 char fhead[12];
 char field_desc[32];
 long pos=0;

 DBF_FIELD *field=NULL;
 DBF_FIELD *cur=NULL;

 if(_dos_open(fname, O_RDWR, &fhandle)!=0)
 {
  printf("不能打开文件:%s/n",fname);
  return NULL;
 }
 db_con = (DBF_CONFIG *)malloc(sizeof(DBF_CONFIG));
 _dos_read(fhandle, fhead, 12, &tmp);
 /*基本信息*/
 db_con->BEGIN_FLAG=(unsigned char)fhead[0];
 memcpy(db_con->LAST_UPPDATE_TIME,fhead+1,3);
 db_con->RECORD_COUNT=*(long*)&fhead[4];
 db_con->HEAD_SIZE=*(unsigned *)&fhead[8];
 db_con->RECORD_SIZE=*(unsigned *)&fhead[10];
 /*状态信息*/
 db_con->DBF_HANDLE=fhandle;
 db_con->current=1;
 /*数据库表属性列表,Delphi3.0创建的数据库表,没有FIELD_X,FIELD_Y字段,Visial FoxPro中有。*/
 /*Delphi3.0的BEGIN_FLAG=03H,Visial FoxPro的BEGIN_FLAG=30H,可据此进行以下的初始化*/
 lseek(fhandle, 0L, SEEK_SET);
 lseek(fhandle, 32L, SEEK_SET);
 pos=1;
 field_x=1;
 while((++pos*32)<db_con->HEAD_SIZE)
 {
  _dos_read(fhandle, field_desc, 32, &tmp);
  field=(DBF_FIELD *)malloc(sizeof(DBF_FIELD));

  memcpy(field->FIELD_NAME,field_desc,11);
  field->FIELD_TYPE=field_desc[11];
  field->FIELD_LENTH=(unsigned char)field_desc[16];
  field->FIELD_FLOAT_LENTH=(unsigned char)field_desc[17];
  if(db_con->BEGIN_FLAG==0x30)
  {
   field->FIELD_X=*(unsigned *)&field_desc[12];
   field->FIELD_Y=*(unsigned *)&field_desc[14];
  }
  else
  {
   field->FIELD_X=field_x;
   field->FIELD_Y=0;
   field_x+=(unsigned)field->FIELD_LENTH;
  }
  field->index=pos-1;
  field->next=NULL;

  if(pos*32==64)
  {
   cur=field;
   db_con->head=field;
  }
  else
  {
   cur->next=field;
   cur=field;
  }

 }
 return db_con;

}

/******************************************
 * 关闭数据库,并且释放DBF_CONFIG内存。
 ******************************************/
int dbfclose(DBF_CONFIG * con)
{
 DBF_FIELD *cur=NULL;
 DBF_FIELD *deleted=NULL;

 if(con==NULL) return 0;
 /*释放DBF_FIELD所占内存*/
 cur=con->head;
 while(cur!=NULL)
 {
  deleted=cur;
  cur=deleted->next;
  free(deleted);
 }
 /*关闭文件句柄*/
 _dos_close(con->DBF_HANDLE);
 /*释放DBF_CONFIG所占内存*/
 free(con);
 return 0;
}

/******************************************
 * 得到DBF_CONFIG中current所指示的记录
 ******************************************/
int dbfread(DBF_CONFIG * con,DBF_RECORD * record)
{
 unsigned tmp;
 if(con==NULL)
 {
  printf("您没有初始化DBF_CONFIG!/n");
  return -1;
 }
 if(record==NULL)
 {
  record=(DBF_RECORD *)malloc(sizeof(DBF_RECORD));
 }
 if(record->value==NULL)
 {
  record->value=(void *)malloc(con->RECORD_SIZE+1);
 }
 lseek(con->DBF_HANDLE, (long)(con->HEAD_SIZE+(con->RECORD_SIZE+1)*(con->current-1)), SEEK_SET);
 _dos_read(con->DBF_HANDLE, record->value, con->RECORD_SIZE+1, &tmp);
 if(con->current<con->RECORD_COUNT)
  con->current++;
 return 0;
}

/******************************************
 * 写入DBF_CONFIG中current所指示的记录
 ******************************************/
int dbfwrite(DBF_CONFIG * con,DBF_RECORD * record)
{
 unsigned tmp;
 lseek(con->DBF_HANDLE, (long)(con->HEAD_SIZE+(con->RECORD_SIZE+1)*(con->current-1)), SEEK_SET);
 _dos_write(con->DBF_HANDLE, record->value, con->RECORD_SIZE+1, &tmp);
 return 0;
}

/******************************************
 * 读取DBF_RECORD相应的FIELD
 * 目前仅支持C-char,N-float,F-float
 * return 0:正确
 *   -1:没有此索引
 *   -2:没有此列名称
 ******************************************/
int dbfgetFieldByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * return_value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 float rfloat;
 unsigned char * temp;
 char float_buf[MAX_FLOAT_LENTH+1];
 while(field!=NULL)
 {
  if(field->index==index)
  {
   /*根据field的类型进行判断,并生成合适的值返回*/
   switch(field->FIELD_TYPE)
   {
    case 'F':
    case 'N':
     temp=(unsigned char *)record->value;
     memcpy(float_buf,temp+field->FIELD_X,field->FIELD_LENTH);
     float_buf[MAX_FLOAT_LENTH]='/0';
     printf("float_buf:%0x/n",float_buf);
     rfloat=atof(float_buf);
     memcpy(return_value,(void *)&rfloat,4);
     printf("rfloat:%f/n",rfloat);
     break;
    case 'C':
    default:
     if(return_value==NULL)
     {
      printf("return_value需要预先分配空间!/n");
      return -1;
     }
     temp=(unsigned char *)record->value;
     memcpy(return_value,temp+field->FIELD_X,field->FIELD_LENTH);
     break;
   }
   return 0;
  }
  field=field->next;
 }
 printf("没有此索引index=%d/n",index);
 return -1;
}
int dbfgetFieldByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * return_value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 int index=0;
 while(field!=NULL)
 {
  if((field->FIELD_LENTH>0)&&(strncmpi(field->FIELD_NAME,name,strlen(name)<field->FIELD_LENTH?strlen(name):field->FIELD_LENTH)==0))
  {
   index=field->index;
   break;
  }
  field=field->next;
 }
 if(index==0)
 {
  printf("没有此列名称name=%s/n",name);
  return -2;
 }
 return dbfgetFieldByIndex(con,record,index,return_value);
}
/*特殊的针对Float-N,Float-F的读取操作*/
/******************************************
 *return 0:正确
 *   -1:没有此索引
 *   -2:没有此列名称
 *   -3:类型不匹配!您试图读取非Float或int型字段
 ******************************************/
int dbfgetFloatByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * return_value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 while(field!=NULL)
 {
  if(field->index==index)
  {
   if(field->FIELD_TYPE=='N'||field->FIELD_TYPE=='F')
    return dbfgetFieldByIndex(con,record,index,return_value);
   else
   {
    printf("类型不匹配!您试图用dbfgetFloatByIndex去读取非Float或int型字段/n");
    return -3;
   }
  }
  field=field->next;
 }
 printf("没有此索引index=%d/n",index);
 return -1;
}
int dbfgetFloatByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * return_value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 int index=0;
 while(field!=NULL)
 {
  if((field->FIELD_LENTH>0)&&(strncmpi(field->FIELD_NAME,name,strlen(name)<field->FIELD_LENTH?strlen(name):field->FIELD_LENTH)==0))
  {
   if(field->FIELD_TYPE=='N'||field->FIELD_TYPE=='F')
   {
    index=field->index;
    break;
   }
   else
   {
    printf("类型不匹配!您试图用dbfgetFloatByName去读取非Float或int型字段/n");
    return -3;
   }
  }
  field=field->next;
 }
 if(index==0)
 {
  printf("没有此列名称name=%s/n",name);
  return -2;
 }
 return dbfgetFieldByIndex(con,record,index,return_value);
}
/*特殊的针对char-C或其他小于等于"MAX_CHAR_LENTH"个字符的串的读取操作*/
/******************************************
 *@return_value:必须在调用此函数前已经声明并分配空间,一般可以定义为unsigned char ret[MAX_CHAR_LENTH+1];
 * return 0:正确
 *   -1:没有此索引
 *   -2:没有此列名称
 ******************************************/
int dbfgetCharByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * return_value)
{
 return dbfgetFieldByIndex(con,record,index,return_value);
}
int dbfgetCharByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * return_value)
{
 return dbfgetFieldByName(con,record,name,return_value);
}

/******************************************
 * 写入DBF_RECORD相应的FIELD
 * 目前仅支持C-char,N-float,F-float
 * value 指向一个float或一个char型数组,若为数组则此数组一般为MAX_CHAR_LENTH长
 *       但一定要大于等于field->FIELD_LENTH,可在数组末尾补齐空格0x20。
 * return 0:正确
 *   -1:没有此索引
 *   -2:没有此列名称
 ******************************************/
int dbfsetFieldByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 unsigned char * temp;
 /*以下用于float和int*/
 float rfloat;
 char f_length[3],f_f_length[3],f_format[10]={"%"};
 char float_buf[MAX_FLOAT_LENTH+1];
 /*以下用于char*/
 unsigned char *temp2;
 while(field!=NULL)
 {
  if(field->index==index)
  {
   /*根据field的类型进行判断,并生成合适的值返回*/
   switch(field->FIELD_TYPE)
   {
    case 'F':
    case 'N':
     rfloat=*(float *)value;
     itoa(field->FIELD_LENTH,f_length,10);
     itoa(field->FIELD_FLOAT_LENTH,f_f_length,10);
     strcat(f_format,f_length);
     strcat(f_format,".");
     strcat(f_format,f_f_length);
     strcat(f_format,"f");
     sprintf(float_buf,f_format,rfloat);
     temp=(unsigned char *)record->value;
     memcpy(temp+field->FIELD_X,float_buf,field->FIELD_LENTH);
     dbfwrite(con,record);
     break;
    case 'C':
    default:
     if(value==NULL)
     {
      printf("value未设定!/n");
      return -1;
     }
     temp=(unsigned char *)record->value;
     temp2=(unsigned char *)value;
     memcpy(temp+field->FIELD_X,temp2,field->FIELD_LENTH);
     dbfwrite(con,record);
     break;
   }
   return 0;
  }
  field=field->next;
 }
 printf("没有此索引index=%d/n",index);
 return -1;
}

int dbfsetFieldByName(DBF_CONFIG * con,DBF_RECORD * record,char * name,void * value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 int index=0;
 while(field!=NULL)
 {
  if((field->FIELD_LENTH>0)&&(strncmpi(field->FIELD_NAME,name,strlen(name)<field->FIELD_LENTH?strlen(name):field->FIELD_LENTH)==0))
  {
   index=field->index;
   break;
  }
  field=field->next;
 }
 if(index==0)
 {
  printf("没有此列名称name=%s/n",name);
  return -2;
 }
 return dbfsetFieldByIndex(con,record,index,value);
}

int dbfsetFloatByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 while(field!=NULL)
 {
  if(field->index==index)
  {
   if(field->FIELD_TYPE=='N'||field->FIELD_TYPE=='F')
    return dbfsetFieldByIndex(con,record,index,value);
   else
   {
    printf("类型不匹配!您试图用dbfgetFloatByIndex去写入非Float或int型字段/n");
    return -3;
   }
  }
  field=field->next;
 }
 printf("没有此索引index=%d/n",index);
 return -1;
}
int dbfsetFloatByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * value)
{
 DBF_FIELD* field=con->head;
 char field_type;
 int index=0;
 while(field!=NULL)
 {
  if((field->FIELD_LENTH>0)&&(strncmpi(field->FIELD_NAME,name,strlen(name)<field->FIELD_LENTH?strlen(name):field->FIELD_LENTH)==0))
  {
   if(field->FIELD_TYPE=='N'||field->FIELD_TYPE=='F')
   {
    index=field->index;
    break;
   }
   else
   {
    printf("类型不匹配!您试图用dbfgetFloatByName去写入非Float或int型字段/n");
    return -3;
   }
  }
  field=field->next;
 }
 if(index==0)
 {
  printf("没有此列名称name=%s/n",name);
  return -2;
 }
 return dbfsetFieldByIndex(con,record,index,value);
}
int dbfsetCharByIndex(DBF_CONFIG * con,DBF_RECORD * record,int index,void * value)
{
 return dbfsetFieldByIndex(con,record,index,value);
}
int dbfsetCharByName(DBF_CONFIG * con,DBF_RECORD * record,char* name,void * value)
{
 return dbfsetFieldByName(con,record,name,value);
}

void main()
{
 dbf_info();
}


/********************工具函数*********************/
char *ccstr( char *str)
{
 char *tok = " ", *p;
 p = strtok( str, tok );
 while( p != NULL)
 {
  if( p != str )
   strcat( str, p );
  p = strtok( NULL, tok );
 }
 return( str );
}

3:结束

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值