DBF PACK
1、创建DBF文件,字段为数字类型时,小数点位置不可以设置。
2、删除DBF记录只是做标记,无法物理删除。
其实,最主要的功能是物理删除记录。为了实现这个功能,我使用过1、复制空的文件,2、创建新DBF文件两种方法。但总觉得不是最好的方式。为了减少执行的时间或避免对目录的操作,让我下决心访问文件的方式来操作DBF。
因为DBF是很久以前流行的数据库,所以在网上还是可以找到相关的资料的,我参照dBase III的文件结构封装了一个操作DBF的C++类。
下面是主要的代码:
//DBF 文件头结构//即库整体描述表,共32个字节
typedef struct tagDBFFILEHEADER
{
unsigned char dfMark; //0x03h 或 0x83h(有MEMORY字段) 0
unsigned char dfYear,dfMmonth,dfDay; //依次为年月日,二进制 1-3
unsigned long dfRecordCount; //总记录个数,低位字节在前 4-7
unsigned short dfHeaderLength; //文件头长度=第9字节值*256+第8字节值 8-9
unsigned short dfRecordLength; //记录长度=第11字节值*256+第10字节值 10-11
unsigned char dfReserved[20]; //保留 12-31
//unsigned char dfFieldDescriptor[33];
}DBFFILEHEADER;
//DBF 字段结构//即字段描述表,32个字节/字段
typedef struct tagDBFFIELDINFO
{
unsigned char diFieldName[11]; //字段名称,ASCII码 0-9
//unsigned char diReserved1; //保留字节 10
unsigned char diFieldType; //字段类型,CDNL等ASCII码11
unsigned long diOffset; //本字段在首记录中的位置 12-15
unsigned char diFieldLength; //字段长度<=256 16
unsigned char diDecimal; //小数点的位数 17
unsigned char diReserved[14]; //保留 18-31
}DBFFIELDINFO;
/* DBF 文件把柄结构 */
typedef struct tagDBFILE
{
FILE *pFile; /* 文件指针 */
DBFFILEHEADER header; /* 文件头结构 */
DBFFIELDINFO *pField; /* 字段结构首指针 */
char fields; /* 字段数 */
}DBFILE;
/* 外部字段信息结构 */
struct tagDBF{
char szFieldName[11]; /* 字段名变量 */
char cbType; /* 字段类型变量 */
unsigned char cbWidth,cbDec; /* 字段长度及小数位变量 */
};
//打开DBF文件
DBFILE * CDBF::Open(char *fName)
{
memset(szFileName, 0, MAX_PATH);
memcpy((char *)&this->szFileName, fName, MAX_PATH);
//打开文件
if((this->dbFile.pFile = fopen(fName, "r+b")) == NULL)
{
return NULL;
}
//读取文件头
if(!fread(&dbFile.header, sizeof(DBFFILEHEADER), 1, dbFile.pFile) || dbFile.header.dfMark!= DBFFILE)
return NULL;
//字段个数
dbFile.fields=(dbFile.header.dfHeaderLength-34)/32+1;
//字段列表
if((dbFile.pField = (DBFFIELDINFO *)malloc(sizeof(DBFFIELDINFO) * dbFile.fields)) == NULL)
return NULL;
if(fread(dbFile.pField, sizeof(DBFFIELDINFO), dbFile.fields, dbFile.pFile) != dbFile.fields)
{
free(dbFile.pField);
return NULL;
}
return &dbFile;
}
bool CDBF::SaveAs(char *fName)
{
if(this->dbFile.pFile)
{
fclose(this->dbFile.pFile);
this->dbFile.pFile=NULL;
remove(this->szFileName);
}
if((this->dbFile.pFile = fopen(fName, "w+b")) == NULL)
{
return false;
}
this->dbFile.header.dfRecordCount= 0l;
SetHeaderDate(&this->dbFile.header);
if(!UpdateHeader(&this->dbFile, 1))
{
return false;
}
memcpy((char *)&this->szFileName, fName, MAX_PATH);
return true;
}