1:HT_DBF.H
/**************************************************************
** c语言操作dbf文件
**
** 目前只支持int--N,char--C
**************************************************************/
#define MAX_INT_LENTH 20
#define MAX_FLOAT_LENTH 20
#define MAX_CHAR_LENTH 254
/***************************************************************
* 数据库表中的列声明,包含一些列属性
* index从0开始
***************************************************************/
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;
/***************************************************************
* 数据库表的配置信息,包含 文件开始标志,最后更新日期,记录总数,文件头大小,记录大小,列属性链表
* 数据库文件句柄,当前记录
* current从0开始
***************************************************************/
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;
extern DBF_CONFIG * dbfopen(char *fname,DBF_CONFIG * db_con);
extern int dbfclose(DBF_CONFIG * con);
extern int dbfsetCurRecNo(DBF_CONFIG * con,int index);
extern int dbfgetField(DBF_CONFIG * con,int fieldno,unsigned char * return_value);
extern int dbfsetField(DBF_CONFIG * con,int fieldno,unsigned char len,unsigned char * value);
extern void dbf_info();
2:HT_DBF.C
#define __ASM asm
#define __HT_DBF 1
#include <ht_dbf.h>
#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>
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;
}
/*读取记录*/
dbfsetCurRecNo(con,1);
dbfgetField(con,0,ret_val);
printf(ret_val);
printf("/n");
/*修改记录*/
dbfsetField(con,0,10,"111111111");
dbfgetField(con,0,ret_val);
printf(ret_val);
printf("/n");
/*关闭数据库*/
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=0L;
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=0;
/*数据库表属性列表,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=0L;
field_x=1;
while((++pos*32+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==32)
{
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);
con=NULL;
return 0;
}
/******************************************
* 设置当前记录,从0开始
*
* return 0:正确
******************************************/
int dbfsetCurRecNo(DBF_CONFIG * con,int index)
{
con->current=index;
return 0;
}
/******************************************
* 读取DBF_RECORD相应的FIELD,字段号从0开始。
*
* return 0:正确
* -1:没有此索引
* -2:没有此列名称
******************************************/
int dbfgetField(DBF_CONFIG * con,int fieldno,unsigned char * return_value)
{
DBF_FIELD* field=con->head;
unsigned temp;
if(return_value==NULL)
{
printf("return_value需要预先分配空间!/n");
return -2;
}
while(field!=NULL)
{
if(field->index==fieldno)
{
/*根据field的类型进行判断,并生成合适的值返回*/
lseek(con->DBF_HANDLE, (long)(con->HEAD_SIZE+(con->RECORD_SIZE)*(con->current)+field->FIELD_X), SEEK_SET);
_dos_read(con->DBF_HANDLE, return_value, field->FIELD_LENTH, &temp);
memset(return_value+field->FIELD_LENTH,'/0',1);
return 0;
}
field=field->next;
}
printf("没有此字段fieldno=%d/n",fieldno);
return -1;
}
/******************************************
* 写入当前记录相应的FIELD,字段号从0开始。
*
* value 指向一个float或一个char型数组,若为数组则此数组一般为MAX_CHAR_LENTH长
* 但一定要大于等于field->FIELD_LENTH,可在数组末尾补齐空格0x20。
* return 0:正确
* -1:没有此索引
* -2:没有此列名称
******************************************/
int dbfsetField(DBF_CONFIG * con,int fieldno,unsigned char len,unsigned char * value)
{
DBF_FIELD* field=con->head;
unsigned temp;
int i;
unsigned char tempstr[MAX_CHAR_LENTH];
if(value==NULL)
{
printf("value未设定!/n");
return -1;
}
for(i=0;i<sizeof(tempstr);i++)
tempstr[i]=' ';
while(field!=NULL)
{
if(field->index==fieldno)
{
if(len>field->FIELD_LENTH) len=field->FIELD_LENTH;
memcpy(tempstr,value,len);
lseek(con->DBF_HANDLE, (long)(con->HEAD_SIZE+(con->RECORD_SIZE)*(con->current)+field->FIELD_X), SEEK_SET);
/*_write(con->DBF_HANDLE, value, len);*/
_dos_write(con->DBF_HANDLE,value,(unsigned)len, &temp);
return 0;
}
field=field->next;
}
printf("没有此字段fieldno=%d/n",fieldno);
return -1;
}
void _main()
{
dbf_info();
}