搜索
bottom↓
回复: 7

c语言对FoxBase的dbf文件操作

[复制链接]

出0入0汤圆

发表于 2012-1-11 10:49:29 | 显示全部楼层 |阅读模式
FoxBASE+数据库语言具有较强的数据组织、管理和检索功能。C语言不仅具有很强的通用程序设计功能,而且很适于处理图形图像、系统程序方面的问题。但总的来说,C语言对大量数据信息的处理不如FoxBASE+语言。如果能在C语言程序中直接调用数据库中的数据,则可充分利用这两种语言的优势。     原来的兰德手持机,如HT-2900对数据库的操作用的是HTbase语言,可以直接对数据表dbf文件操作,很方便。
新出的M73型,芯片是恩智浦的ARM7,lpc2294。操作系统是ucosII.开发完全采用了c语言.编译链接后生成的二进制可执行程序下载到手持机中就可以直接执行。对数据库的dbf文件操作提供了c语言封装好的库函数。以库的形式提供,源代码不可知。有兴趣研究一下。
    要能够用C语言直接存取数据库文件,首先必须搞清楚数据库文件的结构。
  FoxBASE+的数据库文件由两部分组成,第一部分是文件头,其前32个字节是文件的整体描述,接着每32个字节定义一个字段,直到碰到一个0DH(字段描述结束符或称为文件头结束标志)为止;第二部分是实际存放每一个记录的数据部分。前32个字节描述如下: 0
1~3
4~7
8~9
10~11
12~31
1个字节
3个字节
4个字节
2个字节
2个字节
20个字节
03H表示无备注型字段,83H表示有
最后一次修改日期(yy/mm/dd)
.DBF文件的记录数,低字节在前
文件头的长度,低字节在前
记录长度,低字节在前
保留字节


从第32个字节开始到0DH为止是字段描述区,每32个字节定义一个字段,包括字段名、字段类型、字段长度、小数位数等。字段描述的各字节意义如表

起止字节
长  度
含  义

0~10
11
12~15
16
17
18~31
11个字节
1个字节
4个字节
1个字节
1个字节
14个字节
字段名
字段类型(ASCII码)
字段数据在内存中的地址
字段长度(二进制数)
数值字段小数位数(二进制数)
保留字节


    因此,文件头的长度可按下面的公式计算:
  文件头长度=32+(32*定义的字段个数)+1
  在0DH后面,紧接着存放数据记录。记录以定长格式顺序存贮,每个记录的第一个字节是删除标识,有删除标记的记录,该字节是2AH(对应符号“*”),无删除标记的记录,该字节为空格(20H)。每个记录的各字段之间没有分隔符,记录无终止符,各种类型的数据均以ASCII码存放。数据记录之后为一个字节的文尾标识(1AH)。
    按照这个结构就可以对其进行任何操作。但是发现,创建dbf文件时,写入了文件头信息后,虽生成了dbf文件,用foxPro打开后提示不是一个表,说明创建的pdf文件有问题。用UltrEdit打开它,查看它的二进制代码,与一个用foxPro创建的dbf文件做对比,发现少写入了很多信息。dbf文件首先是32个字节的头信息,紧接着是字段描述信息,每个字段描述信息占32个字节,知道0DH,字段描述区结束。后面就开始存储字段的具体数据?错。
发现还要有263个字节的后链信息,现在还不明白这有什么用,但发现没有它建的pdf文件就是错的。所以创建建dbf文件时写入了文件头和字段描述后,紧接着要写入263个0充当后链信息。再写入空格ascII码0x20结束,然后才是字段的数据区。字段数据区的存储也是有规律的。可以根据字段描述区和头文件描述区的信息算出字段数据的地址,然后移动文件指针得到相应字段的数据。

    用C语言直接存取DBF数据库文件的方法
   直接读取DBF数据库记录
  知道了文件头的长度后,要想读取数据库中的记录,可先以“rb”方式打开该数据库文件,然后将文件指针定位于文件头结束标志之后(即第一个记录的开始处),便可逐记录读取该库文件的各记录数据。
   直接更新DBF数据库记录
  如果要更新DBF数据库文件中的某个记录或某个记录中的某字段的内容,可首先用fseek函数将文件指针定位于需修改处,然后用fwrite函数写上新的内容。这里应注意的是,由于DBF数据库中的各记录等长,因而当要写上的新内容不足记录所规定的字节数时,须加空格填满。另外,在对同一数据库进行既读又写的操作时,应以读写二进制方式“rb+”打开该数据库文件。
  对DBF数据库的其它操作
  1.如果要删除DBF数据库中的某记录,可先将要删除记录后面的全部记录读入内存,再将文件指针定位于要删除记录的开始处,之后将读入内存的那些记录重新写回文件中,并将库文件的记录数减1。
  2.如果要在DBF数据库中插入一条记录,可先将文件指针定位于要插入的位置,再将要插入位置后面的全部记录读入内存,然后自插入位置写上(键入)要插入的新记录内容,之后将文件指针移到下一个记录的开始处,把已读入内存的那些记录重新写回文件中,最后将库文件的记录数加1。
  对于这两种操作,由于改变了记录数,因而要注意1AH的位置是否相应地调整了。
下面是示例代码:
头文件信息和字段描述信息的结构体定义:

/*  内部字段信息结构   */
typedef struct DBField{
   char          name[MAXNAMES];   /*  字段名  */
   char           type;             /*  字段类型  */
   void           *teCh;            /*  字段数据地址  */
   unsigned char  width, deC;       /*  字段长度及小数位  */
   char           nul[14];          /*  保留字节  */
}DBFIELD;

/*  DBF 文件头结构  */
typedef struct DBFstr {
   unsigned char  DBF3;                 /*  DBASE 数据文件标记  */
   unsigned char  date_n,date_y,date_r; /*  年月日变量  */
   unsigned long  reCord;               /*  记录数变量    */
   unsigned short ldb,lrd;              /*  头结构.记录长度变量  */
   char           nul[20];              /*  头结构保留字节变量  */
}DBFSTR;

/* DBF 文件句柄结构 */
typedef struct DBFile {
  FILE *fdb;            /*  文件指针  */
  DBFSTR stru;          /*  文件头结构 */
  DBFIELD *start;       /*  字段结构首指针  */
  char fields;          /*  字段数  */
}DBFILE;


/*  外部字段信息结构   */
struct DBF{
   char           name[MAXNAMES];   /*  字段名变量  */
   char           type;             /*  字段类型变量  */
   unsigned char  width,deC;        /*  字段长度及小数位变量  */
};

创建dbf文件函数:
DBFILE *db_Create(char *fname, struct DBF *fd)
{
  DBFILE *f,*db_findfile();
  int n, i = 0;
  if((f = db_findfile()) == NULL) return NULL;
  if((f->fields = db_verifield(fd)) == 0) return NULL;
  if((f->fields = db_verifield(fd)) == 0) return NULL;
  n = sizeof(DBFIELD) * f->fields;
  if((f->start = (DBFIELD *)malloc(n)) == NULL) return NULL;
  memset(f->start, 0, n);
  if((f->fdb = fopen(fname, "w+b")) == NULL){
    free(f->start);
    db_error = 6;
    return NULL;
  }
/* 将定义的外部字段信息拷贝到内部字段结构中 */
  for(i = 0; i < f->fields; i ++)
  {
    strcpy(f->start.name, fd.name);
    f->start.type = fd.type;
    f->start.width = fd.width;
    f->start.deC = fd.deC;
    n += fd.width;
  }
/* 初始化文件头结构 */
  f->stru.DBF3 = DBFFILE;
  f->stru.reCord = 0;
  f->stru.ldb = f->fields * 32 + 296;
  f->stru.lrd = n + 1;
  memset(f->stru.nul, 0, 20);
  db_date(&f->stru);
  if(!db_writestr(f, 1)){
    db_Close(f, 0);
    remove(fname);
    return NULL;
  }
  return f;
}
首先是二进制形式创建并打开一个后缀为dbf的文件,写入文件头信息。在函数db_writestr中写入。
int db_writestr(DBFILE *f, int flag)
{
  int dbend = DBFSTREND;
  int i,tmp=0;
  if(fseek(f->fdb, 0l, 0)) return 0;
  if(!fwrite(&f->stru, sizeof(DBFSTR), 1, f->fdb)) goto err;
  if(flag){
    if(fwrite(f->start, sizeof(DBFIELD), f->fields, f->fdb) != f->fields)
      goto err;
    if(!fwrite(&dbend, 1, 1, f->fdb)) goto err;
  }
  //写后链信息263字节
  for(i=0;i<263;i++)
  {
      fwrite(&tmp, 1, 1, f->fdb);              
  }
  tmp=SPACE;
  if(!fwrite(&tmp, 1, 1, f->fdb)) goto err;
  return 1;
err:
  db_error = 4;
  return 0;
}
由于字段的数据区存储在字段区之后,因此用c去创建dbf文件较为麻烦。比如,如果增加了字段,则相应的原来的字段数据则要整体往后移,腾出字段信息的地方。如果之前建好了dbf文件的字段信息,则操作较为简单。直接读取文件头信息,就能依次访问到记录数据。
调用函数先打开文件:
DBFILE *db_use(char *fname)
{
   DBFILE *f,*db_findfile();
  if((f = db_findfile()) == NULL) return NULL; /* 数据文件打开数超过 MAXFILES */
  if((f->fdb = fopen(fname, "r+b")) == NULL){
    db_error = 2;
    return NULL; /* 文件不存在 */
  }
  if(!db_getstr(f)){
    fclose(f->fdb);
    f->fdb = NULL;
    return NULL;  /* 非 DBASE 数据文件或读文件头信息有错 */
  }
  return f; /* 返回文件指针 */
}
然后读取文件头信息:
int db_getstr(DBFILE *f)
{
/* 读文件头结构 */
  int n=0;
  if(!fread(&f->stru, sizeof(DBFSTR), 1, f->fdb) || f->stru.DBF3 != '0')
    goto err;
/* 读字段结构 */
  f->fields = db_getfields(f->stru);
  if((f->start = (DBFIELD *)malloc(sizeof(DBFIELD) * f->fields)) == NULL)
    goto err;
  if(fread(f->start, sizeof(DBFIELD), f->fields, f->fdb) != f->fields)
  {
    free(f->start);
    goto err;
  }
  return 1;
err:
  db_error = 3;
  return 0;
}
下面是主函数中的测试:
struct DBF dbf;
int main(int argc, char *argv[])
{
  DBFILE *f,*f1;
  char temp[10];
  char temp1[10]="HELLO";
  long int n;
  f=db_use("classes.dbf");
  if(f!=NULL)
  {
    printf("打开成功!\n");         
  }
  else printf("打开失败!\n");
  printf("f->stru.date_n=%d\n",f->stru.date_n);//日期:年
  printf("f->stru.date_y=%d\n",f->stru.date_y);//月
  printf("f->stru.date_r=%d\n",f->stru.date_r);//日
  printf("f->stru.ldb %d\n",f->stru.ldb);//
  printf("f->stru.lrd %d\n",f->stru.lrd);//
  printf("f->stru.reCord %d\n",f->stru.reCord);//
  printf("f->stru.DBF3 %d\n",f->stru.DBF3);//

  printf("字段总数目 fields %d\n",f->fields);//字段数目
// printf("f->start->name %s\n",f->start->name);//字段名字1
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start)->teCh,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("字段名称   %s    %s\n",f->start->name,temp);//
  printf("字段类型   type    %c\n",f->start->type);//字段类型
  printf("字段长度   width   %d\n",f->start->width);//字段长度
  printf("字段小数位 deC     %d\n",f->start->deC);//字段小数位
  printf("字段偏移量 teCh    %d\n",(f->start)->teCh);//
  
// printf("(f->start+1)->name %s\n",(f->start+1)->name);//字段名字2
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+1)->teCh,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+1)->name,temp);//
  printf("type    %c\n",(f->start+1)->type);//字段类型
  printf("width   %d\n",(f->start+1)->width);//字段长度
  printf("deC     %d\n",(f->start+1)->deC);//字段小数位
// printf("(f->start+2)->name %s\n",(f->start+2)->name);//字段名字3
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+2)->teCh,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+2)->name,temp);//
  printf("type    %c\n",(f->start+2)->type);//字段类型
  printf("width   %d\n",(f->start+2)->width);//字段长度
  printf("deC     %d\n",(f->start+2)->deC);//字段小数位
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+3)->teCh,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+3)->name,temp);//
  printf("type    %c\n",(f->start+3)->type);//字段类型
  printf("width   %d\n",(f->start+3)->width);//字段长度
  printf("deC     %d\n",(f->start+3)->deC);//字段小数位
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+4)->teCh,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+4)->name,temp);//
  printf("type    %c\n",(f->start+4)->type);//字段类型
  printf("width   %d\n",(f->start+4)->width);//字段长度
  printf("deC     %d\n",(f->start+4)->deC);//字段小数位
  printf("\n*******************************\n");//
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)f->start->teCh+f->stru.lrd,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",f->start->name,temp);//
  printf("type    %c\n",f->start->type);//字段类型
  printf("width   %d\n",f->start->width);//字段长度
  printf("deC     %d\n",f->start->deC);//字段小数位
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+1)->teCh+f->stru.lrd,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+1)->name,temp);//
  printf("type    %c\n",(f->start+1)->type);//字段类型
  printf("width   %d\n",(f->start+1)->width);//字段长度
  printf("deC     %d\n",(f->start+1)->deC);//字段小数位
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+2)->teCh+f->stru.lrd,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+2)->name,temp);//
  printf("type    %c\n",(f->start+2)->type);//字段类型
  printf("width   %d\n",(f->start+2)->width);//字段长度
  printf("deC     %d\n",(f->start+2)->deC);//字段小数位
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start+3)->teCh+f->stru.lrd,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start+3)->name,temp);//
  printf("type    %c\n",(f->start+3)->type);//字段类型
  printf("width   %d\n",(f->start+3)->width);//字段长度
  printf("deC     %d\n",(f->start+3)->deC);//字段小数位
  fseek(f->fdb,f->stru.ldb,SEEK_SET);
  fseek(f->fdb,f->stru.ldb+(int)(f->start)->teCh+(f->stru.lrd)*2,SEEK_SET);
  fread(temp,10,1,f->fdb);
  temp[9]=0;
  printf("%s    %s\n",(f->start)->name,temp);//
  strcpy(dbf.name,temp1);
  dbf.type='C';
  dbf.width=15;
  dbf.deC=0;
  f1=db_Create("test.dbf",&dbf);
  if(f1!=NULL)
  {
    printf("创建成功!\n");         
  }
  else printf("创建失败!\n");
  printf("f1->stru.date_n=%d\n",f1->stru.date_n);//日期:年
  printf("f1->stru.date_y=%d\n",f1->stru.date_y);//月
  printf("f1->stru.date_r=%d\n",f1->stru.date_r);//日
  printf("字段总数目 fields %d\n",f1->fields);//字段数目
  printf("f1->start->name %s\n",f1->start->name);//字段名字1
  printf("f1->start->type %c\n",f1->start->type);//字段类型
  printf("f1->start->width %d\n",f1->start->width);//字段长度
  printf("f1->start->deC %d\n",f1->start->deC);//字段小数位
  printf("f1->stru.ldb %d\n",f1->stru.ldb);//
  printf("f1->stru.lrd %d\n",f1->stru.lrd);//
  printf("f1->stru.reCord %d\n",f1->stru.reCord);//
  printf("f1->stru.DBF3 %d\n",f1->stru.DBF3);//
  n=ftell(f1->fdb);
  printf("ftell is %d\n",n);
  system("pause");
  return 0;
}

dos窗口显示结果为:

打开成功!
f->stru.date_n=12
f->stru.date_y=1
f->stru.date_r=10
f->stru.ldb 456
f->stru.lrd 66
f->stru.reCord 3
f->stru.DBF3 48
字段总数目 fields 5
字段名称   CLASSID    4
字段类型   type    C
字段长度   width   15
字段小数位 deC     0
字段偏移量 teCh    1
CLASSNAME    one
type    C
width   15
deC     0
UNITS    10
type    C
width   15
deC     0
NAME    xiao
type    C
width   10
deC     0
SEX    nan
type    C
width   10
deC     0

*************************
CLASSID    5
type    C
width   15
deC     0
CLASSNAME    ming
type    C
width   15
deC     0
UNITS    8
type    C
width   15
deC     0
NAME    li
type    C
width   10
deC     0
CLASSID    6
创建成功!
f1->stru.date_n=12
f1->stru.date_y=1
f1->stru.date_r=11
字段总数目 fields 1
f1->start->name HELLO
f1->start->type C
f1->start->width 15
f1->start->deC 0
f1->stru.ldb 328
f1->stru.lrd 48
f1->stru.reCord 0
f1->stru.DBF3 48
ftell is 329
请按任意键继续. . .

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-1-16 09:09:24 | 显示全部楼层
为什么不用开源的 sqlite? 比 foxbase 好用多了吧。

出0入0汤圆

发表于 2012-1-16 09:43:15 | 显示全部楼层
赞同使用sqlite,内存数据库,速度不是foxbase可以比的,foxbase已经退出历史舞台很久了

出0入0汤圆

 楼主| 发表于 2012-1-16 09:57:48 | 显示全部楼层
sqlite,在没操作系统的单片机中呢

出0入0汤圆

发表于 2012-2-27 15:55:43 | 显示全部楼层
其实挺好的,sqlite除非在linux系统里面用。

而dbf文件操作,可以在小内存里面跑的很好。


/*描述*/
/* DBASE.C 中包含了:
   对XBASE数据库文件(.dbf) 进行常用操作的系列函数。
*/
#include <stdio.h>
#include <dos.h>
#include <bios.h>
#include <malloc.h>
#include <mem.h>
#include <conio.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include <stdlib.h>
#include <ctype.h>

#include "dbase.hpp"

#define SUCCESS 0
#define FALSE -1

#define DOS


#ifdef  WINDOWS
static DBF dbfs[30];
static int dbf_used[30]={0};
static char  xzfl_name[20];

DBF *Use(char *dbf_name)
{
/*
Inputs: char *dbf_name --- valid xbase file name
Returns: DBF pointer to  dbase  file  if  successful
         NULL  if  failure
#Description
The Use() funtion opens a xbase file and  returns a
DBF pointer to identify the  xbase file. All subsequent
references to the opened xbase file must be using the
pointer until the file is closed. A xbase file can be
opened only once at one time.
*/
        DBF *dbf=NULL;
        unsigned char byte_buf;
        int i,k;
//    dbf=(DBF *)malloc(sizeof(DBF));

        for(k=0;k<30;k++){
         if(dbf_used[k]==0) {
                dbf_used[k]=1;
                dbf=&dbfs[k];
                break;
         }
        }

        if(dbf==NULL){
           dbf_used[k]=0;
           return NULL;
        }

        if((dbf->dhHandle=fopen(dbf_name,"rb+"))==NULL)
        {
//       free(dbf);
           dbf_used[k]=0;
           return NULL;
         }
        fread(&byte_buf,1,1,dbf->dhHandle);
        if(byte_buf!=0x03&&byte_buf!=0x83)         {
           fclose(dbf->dhHandle);
//       free(dbf);
           dbf_used[k]=0;
           return NULL;
        }
        fread(&byte_buf,1,1,dbf->dhHandle);
        dbf->dhModifyDate.year=(unsigned char)(byte_buf+1900);
        fread(&byte_buf,1,1,dbf->dhHandle);
        dbf->dhModifyDate.month=byte_buf;
    fread(&byte_buf,1,1,dbf->dhHandle);
         dbf->dhModifyDate.day=byte_buf;

    fread(&(dbf->dhRecCount),4,1,dbf->dhHandle);
        fread(&(dbf->dhStruLen),2,1,dbf->dhHandle);

    dbf->dhFieldCount=(dbf->dhStruLen-33)/32;
    fread(&(dbf->dhRecLen),2,1,dbf->dhHandle);
        dbf->dbf_struct=(DBF_STRUCT *)malloc(dbf->dhFieldCount *sizeof(DBF_STRUCT));
    if(dbf->dbf_struct==NULL) {

//       free(dbf);
       dbf_used[k]=0;
           return NULL;
     }

    fseek(dbf->dhHandle,32L,SEEK_SET);
    for(i=0;i<dbf->dhFieldCount;i++)
    {
     fread(dbf->dbf_struct.dhFieldName,11,1,dbf->dhHandle);
     fread(&dbf->dbf_struct.dhFieldType,1,1,dbf->dhHandle);
     fread(&dbf->dbf_struct.dhFieldPos,1,1,dbf->dhHandle);

     fseek(dbf->dhHandle,3L,SEEK_CUR);
     fread(&(dbf->dbf_struct.dhFieldLen),1,1,dbf->dhHandle);
          fread(&(dbf->dbf_struct.dhFieldDec),1,1,dbf->dhHandle);
         fseek(dbf->dhHandle,14L,SEEK_CUR);
    }
        fseek(dbf->dhHandle,1L,SEEK_CUR);
    dbf->dhCurrRec=(char *)malloc(dbf->dhRecLen+1);
    if(dbf->dhCurrRec==NULL) {
       free(dbf->dbf_struct);

//       free(dbf);
       dbf_used[k]=0;
           return NULL;
     }

    if(dbf->dhRecCount>0){
      dbf->dhRecNo=-1;
      fread(dbf->dhCurrRec,dbf->dhRecLen,1,dbf->dhHandle);
      dbf->dhCurrRec[dbf->dhRecLen]=0;
      dbf->dhEof=0;
    }
    else
    { for(i=0;i<dbf->dhRecLen;i++)
            dbf->dhCurrRec=' ';
            dbf->dhCurrRec[dbf->dhRecLen]=0;
                dbf->dhRecNo=0;
            dbf->dhEof=1;
    }
    dbf->dhModify=NO;
    return(dbf);
}
int Close(DBF *dbf)
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
Returns: SUCCESS if successful
         FALSE   if failure
#Description
The Close() function closes a xdbase file
*/
{
  int i;
  char date_tmp[4];
  if(dbf==NULL){
        return FALSE;
  }
  if(dbf->dhModify==YES)
  {
    fseek(dbf->dhHandle,1L,SEEK_SET);
    date_tmp[1]=(char)(dbf->dhModifyDate.year-1900);
    date_tmp[2]=dbf->dhModifyDate.month;
    date_tmp[3]=dbf->dhModifyDate.day;
    fwrite(date_tmp,3,1,dbf->dhHandle);
    fwrite(&(dbf->dhRecCount),4,1,dbf->dhHandle);
  }

  for(i=0;i<10;i++){
   if(dbf->dhHandle==dbfs.dhHandle) break;
  }

  fclose(dbf->dhHandle);
  free(dbf->dhCurrRec);
  free(dbf->dbf_struct);
//  free(dbf);
  dbf_used=0;
  return SUCCESS;
}
#endif

#ifdef DOS
DBF *Use(char *dbf_name) {
/*
Inputs: char *dbf_name --- valid xbase file name
Returns: DBF pointer to  dbase  file  if  successful
         NULL  if  failure
The Use() funtion opens a xbase file and  returns a
DBF pointer to identify the  xbase file. All subsequent
references to the opened xbase file must be using the
pointer until the file is closed. A xbase file can be
opened only once at one time.
*/
        DBF *dbf=NULL;
        unsigned char byte_buf;
        int i,k;
        dbf=(DBF *)malloc(sizeof(DBF));
        if(dbf==NULL){
           return NULL;
        }

        if((dbf->dhHandle=fopen(dbf_name,"rb+"))==NULL)        {
           free(dbf);
           return NULL;
         }
        fread(&byte_buf,1,1,dbf->dhHandle);
        if(byte_buf!=0x03&&byte_buf!=0x83)         {
           fclose(dbf->dhHandle);
           free(dbf);
           return NULL;
        }
        fread(&byte_buf,1,1,dbf->dhHandle);
        dbf->dhModifyDate.year=(unsigned char)(byte_buf+1900);
        fread(&byte_buf,1,1,dbf->dhHandle);
        dbf->dhModifyDate.month=byte_buf;
        fread(&byte_buf,1,1,dbf->dhHandle);
        dbf->dhModifyDate.day=byte_buf;

        fread(&(dbf->dhRecCount),4,1,dbf->dhHandle);
        fread(&(dbf->dhStruLen),2,1,dbf->dhHandle);

    dbf->dhFieldCount=(dbf->dhStruLen-33)/32;
    fread(&(dbf->dhRecLen),2,1,dbf->dhHandle);
    dbf->dbf_struct=(DBF_STRUCT *)malloc(dbf->dhFieldCount *sizeof(DBF_STRUCT));

    if(dbf->dbf_struct==NULL) {
       fclose(dbf->dhHandle);
       free(dbf);   return NULL;
     }

    fseek(dbf->dhHandle,32L,SEEK_SET);
    for(i=0;i<dbf->dhFieldCount;i++)
    {
     fread(dbf->dbf_struct.dhFieldName,11,1,dbf->dhHandle);
     fread(&dbf->dbf_struct.dhFieldType,1,1,dbf->dhHandle);
     fread(&dbf->dbf_struct.dhFieldPos,1,1,dbf->dhHandle);

     fseek(dbf->dhHandle,3L,SEEK_CUR);
     fread(&(dbf->dbf_struct.dhFieldLen),1,1,dbf->dhHandle);
          fread(&(dbf->dbf_struct.dhFieldDec),1,1,dbf->dhHandle);
         fseek(dbf->dhHandle,14L,SEEK_CUR);
    }
        fseek(dbf->dhHandle,1L,SEEK_CUR);
    dbf->dhCurrRec=(char *)malloc(dbf->dhRecLen+1);
    if(dbf->dhCurrRec==NULL) {
       fclose(dbf->dhHandle);
       free(dbf->dbf_struct);
       free(dbf);   return NULL;
     }

    if(dbf->dhRecCount>0){
      dbf->dhRecNo=-1;
      fread(dbf->dhCurrRec,dbf->dhRecLen,1,dbf->dhHandle);
      dbf->dhCurrRec[dbf->dhRecLen]=0;
      dbf->dhEof=0;
    }
    else
    { for(i=0;i<dbf->dhRecLen;i++)
            dbf->dhCurrRec=' ';
            dbf->dhCurrRec[dbf->dhRecLen]=0;
                dbf->dhRecNo=0;
            dbf->dhEof=1;
    }
    dbf->dhModify=NO;
    return(dbf);
}

int Close(DBF *dbf)
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
Returns: SUCCESS if successful
         FALSE   if failure
#Description
The Close() function closes a xdbase file
*/
{
  int i;
  char date_tmp[4];
  if(dbf==NULL){
        return FALSE;
  }
  if(dbf->dhModify==YES)
  {
    fseek(dbf->dhHandle,1L,SEEK_SET);
    date_tmp[1]=(char)(dbf->dhModifyDate.year-1900);
    date_tmp[2]=dbf->dhModifyDate.month;
    date_tmp[3]=dbf->dhModifyDate.day;
    fwrite(date_tmp,3,1,dbf->dhHandle);
    fwrite(&(dbf->dhRecCount),4,1,dbf->dhHandle);
  }

  fclose(dbf->dhHandle);
  free(dbf->dhCurrRec);
  free(dbf->dbf_struct);
  free(dbf);
  return SUCCESS;
}

#endif



long Append(DBF *dbf)
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
Returns: current record no.
#Description
The Append() function adds a blank record to the end of xdbase file
*/
{
  if(dbf==NULL)
  return SUCCESS;

  fseek(dbf->dhHandle,0L,SEEK_END);
  strset(dbf->dhCurrRec,' ');
  dbf->dhCurrRec[dbf->dhRecLen]=0x1a;
  fwrite(dbf->dhCurrRec,dbf->dhRecLen+1,1,dbf->dhHandle);

  fseek(dbf->dhHandle,-1L,SEEK_END);
  dbf->dhCurrRec[dbf->dhRecLen]=0;

  dbf->dhModify=YES;
  dbf->dhRecNo=++(dbf->dhRecCount);
  dbf->dhEof=NO;
  return(dbf->dhRecNo);
}

long Write_Record(DBF *dbf,char *newrecn){
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
        char *newrecn --- pointer to ASCIIZ string,
                          which is the content of a record
Returns: current record no.
#Description
The Write_Record() function overwrites a record to the last record of xdbase file
*/

if(dbf==NULL||dbf->dhRecNo==0)
      return SUCCESS;
strncpy(dbf->dhCurrRec,newrecn,dbf->dhRecLen);
fseek(dbf->dhHandle,(dbf->dhRecNo-1)*(dbf->dhRecLen)+dbf->dhStruLen,SEEK_SET);
fwrite(dbf->dhCurrRec,dbf->dhRecLen,1,dbf->dhHandle);
return(dbf->dhRecNo);
}

long Go(DBF *dbf,unsigned long step){
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
        unsigned long step --- the step form the top of the xbase file
Returns: current record no.
#Description
The Go() function moves the current-record-pointer to the record
whoes record no. is step.
*/

if(dbf==NULL||dbf->dhRecNo==0)
   return SUCCESS;
if(step>dbf->dhRecCount){
    dbf->dhRecNo=dbf->dhRecCount;
    dbf->dhEof=1;
   }
else dbf->dhRecNo=step;
fseek(dbf->dhHandle,(dbf->dhRecNo-1)*(dbf->dhRecLen)+dbf->dhStruLen,SEEK_SET);
fread(dbf->dhCurrRec,dbf->dhRecLen,1,dbf->dhHandle);
return(dbf->dhRecNo);
}

char *Read_Record(DBF *dbf,unsigned long step){
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
        unsigned long step --- the step form the top of the xbase file
Returns: Pointer to ASCIIZ string which is the content of the read record
#Description
The Read_Record() function reads the record  whoes  record no. is step
*/
  if(step>dbf->dhRecCount)
     return("");
  else {
     Go(dbf,step);
     return(dbf->dhCurrRec);
  }
}

int  Write_In(DBF *dbf,char *buf){
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
        char buf --- Pointer to void string which is the content of the written record
Returns: SUCCESS if successful
         FALSE  if failure
#Description
The Write_In() function writes the record  whoes  record no. is step
*/

  int i,j,str_len=0,rec_bar,buf_bar;
  char tmp[100]={0};
  char c_value[20]={0};
  if(dbf==NULL||dbf->dhRecNo==0)
      return SUCCESS;
  tmp[0]=buf[0];//del_flag
  rec_bar=1;  buf_bar=1;
  for(i=0;i<dbf->dhFieldCount;i++){
//       dbf->dbf_struct.dhFieldType;
//       dbf->dbf_struct.dhFieldDec
       switch(dbf->dbf_struct.dhFieldType){
        case 'C':
           for(j=0;j<dbf->dbf_struct.dhFieldLen;j++)
             tmp[rec_bar++]=buf[buf_bar++];
           if(dbf->dbf_struct.dhFieldLen>1)  buf_bar++;
        break;
        case 'N':
           memset(tmp+rec_bar,' ',dbf->dbf_struct.dhFieldLen);
           sprintf(c_value,"%d",*(int *)(buf+buf_bar));
           strcpy(tmp+rec_bar+dbf->dbf_struct.dhFieldLen\
                -strlen(c_value),c_value);
           rec_bar+=dbf->dbf_struct.dhFieldLen;
           buf_bar+=sizeof(int);
        break;
        case 'F':
           memset(tmp+rec_bar,' ',dbf->dbf_struct.dhFieldLen);
           sprintf(c_value,"%.2f",*(float *)(buf+buf_bar));
           strcpy(tmp+rec_bar+dbf->dbf_struct.dhFieldLen\
                -strlen(c_value),c_value);
           rec_bar+=dbf->dbf_struct.dhFieldLen;
           buf_bar+=sizeof(float);
        break;
        case 'L':
           if(*(int *)(buf+buf_bar)==1)  tmp[rec_bar]='T';
           else tmp[rec_bar]='F';
           buf_bar++;
           rec_bar++;
        break;
       }
   }//end for
   for(i=0;i<str_len;i++) if(buf=='\0') buf=' ';
   strncpy(dbf->dhCurrRec,tmp,dbf->dhRecLen);
   fseek(dbf->dhHandle,(dbf->dhRecNo-1)*(dbf->dhRecLen)+dbf->dhStruLen,SEEK_SET);
   fwrite(dbf->dhCurrRec,dbf->dhRecLen,1,dbf->dhHandle);
   return SUCCESS;
}

int  Read_Out(DBF *dbf,char *buf,unsigned long step){
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
        char buf --- Pointer to void string ,to get the record content
Returns: SUCCESS if successful
         FALSE  if failure
#Description
The Read_Out() function reads the record  whoes  record no. is step
*/

  int i,k,pos_bar=0,rec_bar=0;
  float f;
  char tmp[30]={0};

  if(step>dbf->dhRecCount || step<1L)
     return FALSE;
  else {
     Go(dbf,step);
//     return(dbf->dhCurrRec);
     buf[pos_bar++]=*(dbf->dhCurrRec+rec_bar++);
     for(i=0;i<dbf->dhFieldCount;i++){
//       dbf->dbf_struct.dhFieldType;
//       dbf->dbf_struct.dhFieldDec
       memset(tmp,'\0',20);
       switch(dbf->dbf_struct.dhFieldType){
        case 'C':
           if(dbf->dbf_struct.dhFieldLen==1)
              buf[pos_bar++]=*(dbf->dhCurrRec+rec_bar++);
           else {
              for(k=0;k<dbf->dbf_struct.dhFieldLen;k++)
                 buf[pos_bar++]=*(dbf->dhCurrRec+rec_bar++);
              buf[pos_bar++]='\0';
              for(k=0;k<dbf->dbf_struct.dhFieldLen;k++){
//                 if(buf[pos_bar-2-k]==' ') buf[pos_bar-2-k]='\0'; //modified by lq ,1997\08\09
//                 else break;
              }
           }
         break;
         case 'N':
              for(k=0;k<dbf->dbf_struct.dhFieldLen;k++)
                 tmp[k]=*(dbf->dhCurrRec+rec_bar++);
              *(int *)(buf+pos_bar)=atoi(tmp);
              pos_bar+=sizeof(int);
         break;
         case 'F':
                  for(k=0;k<dbf->dbf_struct.dhFieldLen;k++)
                 tmp[k]=*(dbf->dhCurrRec+rec_bar++);
              for(k=0;;k++) if(tmp[k]!=' ') break;
              f=atoi(tmp);
              for(k=0;;k++) if(tmp[k]=='.') break;
              k++;
              f+=(tmp[k++]-'0')*0.1;
              f+=(tmp[k]-'0')*0.01;
              *(float *)(buf+pos_bar)=f;
              pos_bar+=sizeof(float);
         break;
         case 'L':
                 tmp[0]=*(dbf->dhCurrRec+rec_bar++);
                 if(tmp[0]=='F') *(int *)(buf+pos_bar)=0;
                 else  *(int *)(buf+pos_bar)=1;
                 pos_bar+=1;
         break;
         default: break;
       }//end switch
     }
  }
  return SUCCESS;
}


long  Skip(DBF *dbf,int step){
/*
Inputs: DBF *dbf --- DBF pointer to xbase file
        int step --- the steps to move from current record.
Returns:the current record no.
#Description
The Skip() function moves the current-record-pointer.
*/

  if(dbf==NULL||dbf->dhRecNo==0)
       return SUCCESS;
  if(dbf->dhRecNo+step<1)
      step=1-dbf->dhRecNo;
  else if(dbf->dhRecNo+step>dbf->dhRecCount)
  {
      step=dbf->dhRecCount-dbf->dhRecNo;
      dbf->dhEof=1;
  }
  dbf->dhRecNo+=step;
  if(step!=1)
      fseek(dbf->dhHandle,dbf->dhRecLen*(step-1),SEEK_CUR);
  fread(dbf->dhCurrRec,dbf->dhRecLen,1,dbf->dhHandle);
  return(dbf->dhRecNo);
}

/*
int MyCopy(char *source,char *dest){
int readlen=4096;
int readcnt;
char ptr[4100]={0};
FILE *fp1,*fp2;
fp1=fopen(source,"rb");
if(fp1==NULL) return -1;

fp2=fopen(dest,"wb");
if(fp2==NULL) {
   fclose(fp1);
   return  -1;
}
for(;;){
#ifdef MTASk
  //... save filepos
  tDelay(0);
  //... restore filepos
#endif
  readcnt=fread(ptr,1,readlen, fp1);
  if(readcnt)  { fwrite(ptr,1,readcnt,fp2); fflush(fp2);}
  if(readcnt!=readlen) break;
}
fclose(fp1); fclose(fp2);
return 0;
}
*/

int MyStrcmp(char *source,char *match){
  int i,len;
  int retv=0;
  len=strlen(match);
  for(i=0;i<len;i++){
    if(match=='?') continue;
    if(source==match) continue;
    else { retv=-1;break;}
  }
  return retv;
}

int Find(DBF *dbf,char *match,int match_pos,long startno,long *recno){
/*
match---match string
match_pos---the start matching position in the record string.
//match_pos=(sun of the previous field lenth)+1
startno---the start recordno in the dbf
recno---the first matched record no in dbf
return --- SUCCESS , FALSE
note: char '?' in match string,indicate that this char is ignored in matching.
*/
   int found=0,i,j;
//   char record[200]={0};
   char *record;

   if(Go(dbf,startno)!=startno) return FALSE;

   record=new char[dbf->dhRecLen];
   if(!record) {
     printf("\nError: cannot alloc mem,in Find()");
     return FALSE;
   }

   *recno=startno;
   for(i=startno;!eof(dbf);i++){
      strcpy(record,Read_Record(dbf,i));
      Skip(dbf,1);  (*recno)=i;
      if(record[0]!=' ') continue;
      if(MyStrcmp(record+match_pos,match)==0)   found=1;
      else found=0;
      if(found) break;
   }

   delete record;

   if(found)  return SUCCESS;
   else   return FALSE;
}


--------------
#define recount(dbf) (dbf->dhRecCount)
#define recno(dbf) (dbf->dhRecNo)
#define isdeleted(dbf)(*(dbf->dhCurrRec)=='*')
#define eof(dbf)(dbf->dhEof)
#define field_name(dbf,field_no)((dbf)->dbf_struct[(field_no)-1].dhFieldName)
#define YES 1
#define NO 0

typedef struct {
       int dhType;
       struct date dbModifyDate;
       long dhRecCount;
       unsigned dhStruLen;
       int DhFieldCount;
       int dhRecLen;
       char dhReserved[18];
} DBFHEAD;

typedef struct {
  int dhHandle;
      unsigned  dhFileSize;
} DBTHead;

typedef struct {
  char dhFieldName[11];
      char  dhFieldType;
      char  dhFieldLen;
      char  dhFieldDec;
      int   dhFieldPos;
} DBF_STRUCT;

struct dhDate{
  unsigned char year;
  unsigned  char month;
  unsigned char day;
};

typedef struct {
      FILE     *dhHandle;
      struct  dhDate dhModifyDate;
      long     dhRecCount;
      unsigned int dhStruLen;
      int   dhFieldCount;
      int      dhRecLen;
      DBF_STRUCT *dbf_struct;
      long  dhRecNo;
      char   *dhCurrRec;
      int   dhEof;
      int   dhModify;
      }DBF;

typedef struct{
   int handle;
      unsigned long filesize;
      }DBT;
/*
      typedef struct{
      int handle;
      long filesize;
      long node_position;
      long root_position;
      int i_p_node;
      int text_len;
      char *key;
      char key_type;
      int  key_len;
      NODE *node;
      int node_type;
      int  i_count;
      long per_node;
      long suc_node;
      NODE *i_front;
      NODE *i_rear;
      NODE *u_curr;
      int update_tag;
     }IDX;
  */
     int  Write_In(DBF *dbf,char *buf);
     int  Read_Out(DBF *dbf,char *buf,unsigned long step);
     long Write_Record(DBF *dbf,char *newrecn);
     char *Read_Record(DBF *dbf,unsigned long step);
     DBF  *Use(char *);
     int  Create(char *dbf_name,int dhFieldCount,DBF_STRUCT *dbf_stru);
     int  Close(DBF *dbf);
     long Go(DBF *dbf,unsigned long step);
     long Delete(DBF *dbf);
     long Recall(DBF *dbf);
     long Skip(DBF *dbf,int step);
     long Append(DBF *dbf);
     int  CreateDbf(int flag,char *filename);

     int MyStrcmp(char *source,char *match);
     int Find(DBF *dbf,char *match,int match_pos,long startno,long *recno);

出0入0汤圆

发表于 2012-2-27 16:26:59 | 显示全部楼层
SQLITE才是王道

出0入0汤圆

发表于 2013-7-25 21:58:16 | 显示全部楼层
关注DBASE

出0入0汤圆

发表于 2013-7-26 00:11:18 | 显示全部楼层
就是,干嘛不彻底点你干脆用dbase好了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 09:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表