C语言对DBF数据库文件的操作
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文件头长度=32+(32*定义的字段个数)+1 在 0DH 后面,紧接着存放数据记录。记录以定长 格式顺序存贮,每个记录的第一个字节是删除标识,有删除标记的记录,该字节是 2AH(对 应符号 “*”),无删除标记的记录,该字节为空格(20H)。每个记录的各字段之间没有分隔 符,记录无终止符,各种类型的数据均以 ASCII 码存放。数据记录之后为一个字节的文尾 标识(1AH)。
typedef struct{ /* dbf 文件头结构 */ char vers; /* 版本标志*/ unsigned char yy,mm,dd; /* 最后更新年、月、日 */ unsigned long no_recs; /* 文件包含的总记录数 */ unsigned short head_len,rec_len; /* 文件头长度,记录长度 char reserved[20]; /* 保留 */ } dbf_head; typedef struct{ /* 字段描述结构 */ char field_name[11]; /* 字段名称 */ char field_type; /* 字段类型 */ unsigned long offset; /* 偏移量 */ unsigned char field_length; /* 字段长度 */ unsigned char field_decimal; /* 浮点数整数部分长度 */ char reserved1[2]; /* 保留 */ char dbaseiv_id; /* dbase iv work area id */ char reserved2[10];
strstore(crecord.userid, dbfitem.userid, m_useridlen); strstore(crecord.username, dbfitem.username, m_usernamelen); strstore(crecord.area, dbfitem.area, m_arealen); } void strstore(char *src, char *dest, int len){// dest 里的值存到 src int i, j; i=strlen(src); if (i>len) i=len; for (j=0; j<i; j++) *dest++=*src++; while (j<len) { *dest++=' '; j++; } }
C 语言对 DBF 数据库文件的操作
1.DBF 数据库文件的结构
要能够用 C 语言直接存取数据库文件,首先必须搞清楚数据库文件的结构。 DBF 文件由两部分组成,第一部分是文件头,其前 32 个字节是文件的整体描述,接着 每 32 个字节定义一个字段,直到碰到一个 0DH (字段描述结束符或称为文件头结束标志)为 止;第二部分是实际存放每一个记录的数据部分。文件头部分的前 32 个字节说明如表 1。 表1 库文件的整体描述 长 度 1 个字节 3 个字节 4 个字节 2 个字节 2 个字节 20 个字节 含 义 03H 表示无备注型字段,83H 表示有 最后一次修改日期(yy/mm/dd) DBF 文件的记录数,低字节在前 文件头的长度,低字节在前 记录长度,低字节在前 保留字节
2.用 C 语言直接存取 DBF 数据库文件的方法
直接读取 DBF 数据库记录 知道了文件头的长度后,要想读取数据库中的记录,可先以“rb”方式打开该数据库文 件,然后将文件指针定位于文件头结束标志之后(即第一个记录的开始处),便可逐记录读取 该库文件的各记录数据。 2.2 直接更新 DBF 数据库记录 如果要更新 DBF 数据库文件中的某个记录或某个记录中的某字段的内容,可首先用 2.1
//file_head.no_recs=c[0]+
c[1]*0x100+
c[2]*0x10000+
Biblioteka Baidu
_dos_read(fhandle, buffer, file_head.rec_len+1, &tmp); dbfseek(file_head.no_recs ); _dos_write(fhandle, &dbfitem, file_head.rec_len, &tmp); dbfseek(file_head.no_recs+1); file_head.no_recs = file_head.no_recs + 1; _dos_write(fhandle, buffer, file_head.rec_len + 1, &tmp); sprintf(c, "%-c", file_head.no_recs); lseek(fhandle, 4L,SEEK_SET); _dos_write(fhandle, c, 4, &tmp); } void dbfread(C_REC *crecord){ unsigned tmp; _dos_read(fhandle, &dbfitem, file_head.rec_len, &tmp); convDBF2C(crecord); } void dbfwrite(C_REC crecord){ unsigned tmp; convC2DBF(crecord); _dos_write(fhandle, &dbfitem, file_head.rec_len, &tmp); } int nextrecord(void) { if (currec < numofrec) { currec++; return 1; } else return 0; } void convDBF2C(C_REC *crecord){ strncpy(crecord->userid, dbfitem.userid, m_useridlen); crecord->userid[m_useridlen]=0; strncpy(crecord->username, dbfitem.username, m_usernamelen); crecord->username[m_usernamelen]=0; strncpy(crecord->area, dbfitem.area, m_arealen); crecord->area[m_arealen]=0; } void convC2DBF(C_REC crecord){
fseek 函数将文件指针定位于需修改处,然后用 fwrite 函数写上新的内容。这里应注意的是, 由于 DBF 数据库中的各记录等长,因而当要写上的新内容不足记录所规定的字节数时,须 加空格填满。另外,在对同一数据库进行既读又写的操作时,应以读写二进制方式“rb+” 打开该数据库文件。 2.3 对 DBF 数据库的插入删除操作 1.如果要删除 DBF 数据库中的某记录,可先将要删除记录后面的全部记录读入内存, 再将文件指针定位于要删除记录的开始处, 之后将读入内存的那些记录重新写回文件中, 并 将库文件的记录数减 1。 2.如果要在 DBF 数据库中插入一条记录,可先将文件指针定位于要插入的位置,再将 要插入位置后面的全部记录读入内存,然后自插入位置写上(键入)要插入的新记录内容,之 后将文件指针移到下一个记录的开始处, 把已读入内存的那些记录重新写回文件中, 最后将 库文件的记录数加 1。 对于这两种操作,由于改变了记录数,因而要注意 1AH 的位置是否相应地调整了。 例子:在 Borland c 下编译成功,如果在其他编译器下不成功,因为 dos.h 不一样。只要改 写文件操作方法就好 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #include <dos.h> #include <io.h> #define m_useridlen #define m_usernamelen #define m_arealen 10 30 20
*/
char production_index; } field_element; typedef struct { char userid[m_useridlen]; char username[m_usernamelen]; char area[m_arealen]; } DBF_REC; typedef struct { char userid[m_useridlen+1]; char username[m_usernamelen+1]; char area[m_arealen+1]; } C_REC; dbf_head file_head; field_element *fields; DBF_REC dbfitem,tempitem; C_REC thisitem; int dbfopen(char *fname, int *fhdl){ unsigned tmp; while (_dos_open(fname, O_RDWR, fhdl)!=0) exit(0); _dos_read(*fhdl, &file_head, sizeof(dbf_head),&tmp); return(0); } void dbfclose(void){ _dos_close(fhandle); } void dbfseek(long recnum){ lseek(fhandle, (recnum-1)*file_head.rec_len + file_head.head_len, SEEK_SET); } void dbfinsert(C_REC crecord) { unsigned char c[4]={0,0,0,0}; c[3]*0x1000000 unsigned tmp; unsigned char buffer[256]; convC2DBF(crecord); dbfseek(file_head.no_recs);
起止字节 0 1~3 4~7 8~9 10~11 12~31
从第 32 个字节开始到 0DH 为止是字段描述区,每 32 个字节定义一个字段,包括字段名、 字段类型、字段长度、小数位数等。字段描述的各字节意义如表 2。 表 2 字段描述 起止字节 0~10 11 12~15 16 17 18~31 长 度 11 个字节 1 个字节 4 个字节 1 个字节 1 个字节 14 个字节 含 义 字段名 字段类型(ASCII 码) 字段数据在内存中的地址 字段长度(二进制数) 数值字段小数位数(二进制数) 保留字节