`
sogotobj
  • 浏览: 617704 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

C语言版的DBF本地数据库文件操作函数

阅读更多

几个月前,翻出以前的一些1993 - 1995年的C/C++老代码,陆续粘贴到了BLOG上,一来以免不小心遗失(以前很多好代码都丢了),二来可供C/C++爱好者,特别是初学者借鉴参考,本以为就这些了,没料到月头又找出一些更老的代码,都是1991年及以前的,前几天我发上来的《C语言版的磁盘文件分片归并排序函数》就是其中之一。今天准备把1991年用TURBOC 2.0写的DBF本地数据库文件操作函数完整的贴在这里,前几个月发的文章《C++老代码 -- DBF数据文件操作类DBFile》应该是我当时从C向C++过渡时根据这里的C代码改写的。

其实还有个通用的用B+树建立本地数据索引文件的工具代码,本想在《C语言版的磁盘文件分片归并排序函数》之后贴上来,但是由于目前32位计算机与以前的16位计算机的数据类型长度不一样,而索引文件是分索引节点块写道磁盘文件上的,数据类型长度不同必定引起移植错误(以前没想这么多 ^_^ ),再看到《C语言版的磁盘文件分片归并排序函数》很受朋友们捧场(一天的电击量达到了1000多),错误多了会挨骂的,所以,只能等春节后找几天时间改一下(代码很长很复杂的)后再贴出来。顺便在此感谢大家的捧场,也感谢CSDN编辑把文章挂在了首页,才能让这么多的朋友光临。

需要说明的是,1991年我正好业余学习计算机语言2年多时间,其中包括学习BASIC、PASCAL及汇编等,所以C语言可能掌握的不大好,更谈不上代码设计,加上我又不懂英语,标识符命名也不规范等,因此有什么不对的地方可以写信给我(maozefa@hotmail.com),也可留言,但是代码在16位机上绝对是可行的,记得我以前经常用的,但是要用到32位机上,和DBF文件有关的几个结构的数据类型要改一下,很简单的,只是把int变为short就行了的(好像就2处地方),我自己没改是因为该代码与2个通用排序函数不一样,目前实用价值不大,就让它保持原样吧!

下面是代码,没写测试程序:

/*
*********************DBASE数据文件操作C库文件************************
*文件名:MDBFIO.H*
*编制人:湖北省公安县统计局毛泽发*
*日期:1991.8*
***************************************************************************
*/
#include
<stdio.h>

#defineMAXFILES10
#defineMAXFIELD128/*......记录最大字段数*/
#defineMAXNAMES11/*......字段名最大长度*/
#defineMAXFIESIZE254/*......字符字段最大位数*/
#defineMAXWIDTH19/*......数据字段最大位数*/
#defineMAXDEC15/*......数据小数最大位数*/
#defineDBFFILE3/*......头结构开始标记*/
#defineDBFSTREND0x000d/*......头结构结束标记*/
#defineDBFEND26/*......文件结束标记*/
#defineDELFLAG'*'/*记录删除标记*/
#defineTOP0l/*首记录标志*/
#defineBOTTOM-1/*末记录标志*/
#defineSPACE32

/*内部字段信息结构*/
typedef
structdbfield{
charname[MAXNAMES];/*字段名*/
chartype;/*字段类型*/
voidfar*tech;/*字段数据地址*/
unsigned
charwidth,dec;/*字段长度及小数位*/
charnul[14];/*保留字节*/
}DBFIELD;

/*DBF文件头结构*/
typedef
structdbfstr{
unsigned
chardbf3;/*DBASE数据文件标记*/
unsigned
chardate_n,date_y,date_r;/*年月日变量*/
unsigned
longrecord;/*记录数变量*/
unsigned
intldb,lrd;/*头结构.记录长度变量*/
charnul[20];/*头结构保留字节变量*/
}DBFSTR;

/*DBF文件把柄结构*/
typedef
structdbfile{
FILE
*fdb;/*文件指针*/
DBFSTRstru;
/*文件头结构*/
DBFIELD
*start;/*字段结构首指针*/
charfields;/*字段数*/
}DBFILE;


/*外部字段信息结构*/
structdbf{
charname[MAXNAMES];/*字段名变量*/
chartype;/*字段类型变量*/
unsigned
charwidth,dec;/*字段长度及小数位变量*/
};
/*db_errorDBASE文件操作出错信息:
0:无错误;1:打开文件过多;2:文件未找到;3:读文件头失败;4:写文件头失败;
5:关闭文件失败;6:打开文件失败;7:移动文件指针出错.
*/
externunsignedchardb_error;

intdb_getfields(DBFSTRstr);/*计算并返回文件字段数*/
voidundberror(void);/*清除DB_ERROR错误信息*/
intdb_getstr(DBFILE*f);/*读文件头信息,成功返回1,否则0*/
DBFILE
*db_use(char*fname);/*打开一个已存在文件,返回指针供读写,出错返回NULL*/
/*根据外部字段结构创建一个.DBF文件,成功返回指针供读写,出错返回NULL*/
DBFILE
*db_create(char*fname,structdbf*fd);
/*关闭一个文件,FLAG=0,不更新文件头,否则更新;成功返回1,否则0*/
intdb_close(DBFILE*f,intflag);
/*写文件头信息,FLAG=0不写字段信息,成功返回1,否则0*/
intdb_writestr(DBFILE*f,intflag);
longdb_cpyrec(DBFILE*fo,DBFILE*fi,longfosta,longfista,longn,int*fields);
longdb_fappend(DBFILE*fo,DBFILE*fi,longstarec,longn,int*fields);
intdb_copy(char*tofname,char*ffname,intflag,longstarec,longn,int*fields);
longdb_goto(DBFILE*f,longrecord);
longdb_getrecnum(DBFILE*f);
longdb_skip(DBFILE*f,longn);
intdb_delete(DBFILE*f,longrecs);
intdb_recall(DBFILE*f,longrecs);
intdb_pack(char*fname);
/***DBFIO.HEND***/

/*
*********************DBASE数据文件操作C库文件************************
*文件名:DB_CLOSE.C*
*编制人日期:湖北省公安县统计局毛泽发(1991.8)*
***************************************************************************
*/
#include
<dos.h>
#include
<stdlib.h>
#include
"dbfio.h"
#ifdefTURBOC
#include
<alloc.h>
#else
#include
<malloc.h>
#endif
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:DB_DATE*
*参数:DAT数据文件头结构指针*
*功能:读系统当前时间到头结构中*
*返回值:*
***************************************************************************
*/
voiddb_date(DBFSTR*dat)
{
char*p,q[5];
unionREGSinr;
inr.h.ah
=0x2a;
intdos(
&inr,&inr);
p
=itoa(inr.x.cx,q,10)+2;
dat
->date_n=atoi(p);
dat
->date_y=inr.h.dh;
dat
->date_r=inr.h.dl;
}
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:DB_CLOSE*
*参数:fDBASE数据文件指针*
*功能:关闭一个DBASE数据文件*
*返回值:成功1,否则0*
***************************************************************************
*/
intdb_close(DBFILE*f,intflag)
{
if(!f->fdb)return0;/*无效文件号*/
if(flag){/*如已向文件写数据,更新文件头结构*/
db_date(
&f->stru);
if(!db_writestr(f,0))return0;
}
if(fclose(f->fdb)==EOF){
db_error
=5;
return0;
}
free(f
->start);
f
->fdb=NULL;
return1;
}
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:db_writestr*
*参数:f:DBASE数据文件指针,flag=0不写字段信息,否则整个文件头信息*
*功能:写文件头信息到数据文件*
*返回值:成功1,否则0*
***************************************************************************
*/
intdb_writestr(DBFILE*f,intflag)
{
intdbend=DBFSTREND;
if(fseek(f->fdb,0l,0))return0;
if(!fwrite(&f->stru,sizeof(DBFSTR),1,f->fdb))gotoerr;
if(flag){
if(fwrite(f->start,sizeof(DBFIELD),f->fields,f->fdb)!=f->fields)
gotoerr;
if(!fwrite(&dbend,sizeof(int),1,f->fdb))gotoerr;
}
return1;
err:
db_error
=4;
}
/***DB_CLOSE.CEND***/

/*
*********************DBASE数据文件操作C库文件************************
*文件名:DB_COPY.C*
*编制人日期:湖北省公安县统计局毛泽发(1991.8)*
***************************************************************************
*/
#include
"dbfio.h"
#ifdefTURBOC
#include
<alloc.h>
#else
#include
<malloc.h>
#endif
#include
<string.h>
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:DB_COPY*
*参数:tofname:复制文件名;ffname:被复制文件名;flag:0只复制结构,1包*
*括记录;starec:起始记录(0-N);n:记录数;如n=0,start及以下全*
*部记录;fileds:字段序号表,以-1结尾,如fields=0复制全部字段*
*功能:按条件复制一个文件内容到另一文件中*
*返回值:成功0,被复制文件不存在-1,复制失败-2*
***************************************************************************
*/
intdb_copy(char*tofname,char*ffname,intflag,longstarec,longn,
int*fields)
{
DBFILE
*fi,*fo,*db_findfile();
register
inti=0,j;
if((fo=db_findfile())==NULL)return-2;
if((fo->fdb=fopen(tofname,"w+b"))==NULL){
db_error
=6;
return-2;
}
if((fi=db_use(ffname))==NULL)return-1;
memcpy((
char*)&fo->stru,(char*)&fi->stru,sizeof(DBFSTR));
if(!fields){
fo
->start=fi->start;
fo
->fields=fi->fields;
}
else{
for(;fields[i]>=0&&fields[i]<fi->fields&&i<MAXFIELD;i++);
j
=sizeof(DBFIELD)*i;
if((fo->start=(DBFIELD*)malloc(j))==NULL){
db_close(fi,
0);
fclose(fo
->fdb);
fo
->fdb=NULL;
return-2;
}
memset(fo
->start,0,j);
fo
->fields=i;
fo
->stru.lrd=0;
for(i=0;i<fo->fields;i++){
j
=fields[i];
memcpy((
char*)&fo->start[i],(char*)&fi->start[j],sizeof(DBFIELD));
fo
->stru.lrd+=fo->start[i].width;
}
fo
->stru.lrd+=1;
fo
->stru.ldb=i*32+34;
}
if(flag)db_cpyrec(fo,fi,0l,starec,n,fields);
db_close(fi,
0);
i
=db_writestr(fo,1);
if(fields)free(fo->start);
fclose(fo
->fdb);
fo
->fdb=NULL;
if(!i){
remove(tofname);
return-2;
}
}
/***DB_COPY.CEND***/
/*
*********************DBASE数据文件操作C库文件************************
*文件名:DB_CPYRE.C*
*编制人日期:湖北省公安县统计局毛泽发(1991.8)*
***************************************************************************
*/
#include
"dbfio.h"
#ifdefTURBOC
#include
<alloc.h>
#else
#include
<malloc.h>
#endif
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:DB_CPYREC*
*参数:fo,fi:分别为复制.被复制文件指针;fosta,fista:分别为fo,fi所指文*
*件起始记录;n:记录数,n=0,包括fista在内以下全部记录;fields;*
*字段序号表,为NULL复制全部字段*
*功能:复制fi文件的记录到fo文件,如fo与fi或者fields字段数.*
*对应字段类型.长度及小数不匹配,数据库会出错*
*返回值:fo文件实际记录数(注:必须调用DB_CLOSE关库后,文件记录才更新)*
***************************************************************************
*/
longdb_cpyrec(DBFILE*fo,DBFILE*fi,longfosta,longfista,longn,
int*fields)
{
registerunsigned
longi;
unsigned
longp,q;
register
intj,k;
char*buf;
if((buf=(char*)malloc(fi->stru.lrd))==NULL)return0l;
if(db_goto(fo,fosta)==-1l||db_goto(fi,fista)==-1l)return0l;
if(!n)n=fi->stru.record-fista;
if(!fields){
for(i=0l;i<n;i++){
if(!fread(buf,fi->stru.lrd,1,fi->fdb))break;
if(*buf==DELFLAG){
i
--;n--;
continue;
}
if(!fwrite(buf,fo->stru.lrd,1,fo->fdb))break;
}
}
else{
char*s,*p;
intm,h;
if((s=(char*)malloc(fo->stru.lrd))==NULL)return0l;
for(i=0l;i<n;i++){
p
=s;
if(!fread(buf,fi->stru.lrd,1,fi->fdb))break;
if(*buf==DELFLAG){
i
--;n--;
continue;
}
*p++=*buf;
for(m=0;fields[m]>=0;m++){
for(k=0,j=1;k<fields[m];j+=fi->start[k].width,k++);
for(h=k,k=j,j+=fi->start[h].width;k<j;k++)*p++=buf[k];
}
if(!fwrite(s,fo->stru.lrd,1,fo->fdb))break;
}
free(s);
}
free(buf);
fo
->stru.record=fosta+i;
returnfo->stru.record;
}
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:DB_FAPPEND*
*参数:starec:为被追加文件起始记录.其余参数同DB_CPYREC.*
*功能:追加fi文件的记录到fo文件尾部,其它同DB_CPYREC*
*返回值:fo文件实际记录数,其它同DB_CPYREC*
***************************************************************************
*/
longdb_fappend(DBFILE*fo,DBFILE*fi,longstarec,longn,int*fields)
{
return(db_cpyrec(fo,fi,fo->stru.record,starec,n,fields));
}
/***DB_CPYRE.CEND***/

/*
*********************DBASE数据文件操作C库文件************************
*文件名:DB_CREAT.C*
*编制人日期:湖北省公安县统计局毛泽发(1991.8)*
***************************************************************************
*/
#include
"dbfio.h"
#ifdefTURBOC
#include
<alloc.h>
#else
#include
<malloc.h>
#endif
#include
<string.h>
/*
*********************DBASE数据文件操作C库函数***********************
*函数名:DB_VERIFIELD*
*参数:fd:外部字段结构数组首指针,末尾字段名首字符应为""*
*功能:检验并校正字段类型.长度和小数位*
*返回值:字段数*
***************************************************************************
*/
intdb_verifield(structdbf*fd)
{
register
inti,j;
for(i=0;fd[i].name[0]&&i<MAXFIELD;i++){
if(fd[i].type>'b'&&fd[i].type<'o')fd[i].type-=32;
if(fd[i].type!='N')fd[i].dec=0;
if(fd[i].width==0)fd[i].width=1;
switch(fd[i].type){
case'C':
if(fd[i].width>MAXFIESIZE)fd[i].width=MAXFIESIZE;
break;
case'N':
if(fd[i].dec>MAXDEC)fd[i].dec=MAXDEC;
if(fd[i].width>MAXWIDTH)fd[i].dec=MAXWIDTH;
if((fd[i].width-fd[i].dec)<2)fd[i].width=fd[i].dec+2;
break;
case'L':
fd[i].width
=1;break;
case'D':
fd[i].width
=8;break;
case'M':
fd[i].width
=10;break;
default:
if(fd[i].name[0color: #0000
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics