C++老代碼 -- DBF數據文件操作類DBFile

http://sogotobj.iteye.com/blog/1065023

十幾年前,dBASE、FoxBase和FoxPro數據庫盛極一時,C/C++程序員使用C/C++直接操作DBF數據文件是理所當然的事,下面是我在1994年寫的一個DBFile類代碼。

DBFIle類的頭文件:

//DBFIO.HPP

#ifndef__DBFIO_HPP
#define__DBFIO_HPP

#include
<stdlib.h>
#include
<fstream.h>
#include
"marray.hpp"

constint

DB_FieNameSize
=11;

classDBField//DBF文件的字段類
{

public:

charname[DB_FieNameSize];
chartype;
intoff;
intnul;
unsigned
charwidth;
unsigned
chardec;
DBField()
{
memset(
this,0,sizeof(DBField));
}
intoperator==(constDBField&);
intoperator<(constDBField&);
DBField
&operator=(constDBField&);
//設置字段.參數:名稱,類型,寬度,小數位
voidSetValue(char*,int,int,int=0);
};

inline
intDBField::operator==(constDBField&d)
{
return!strcmp(name,d.name);
}

inline
intDBField::operator<(constDBField&d)
{
returnstrcmp(name,d.name)<0?1:0;
}

inlineDBField
&DBField::operator=(constDBField&d)
{
memmove(
this,&d,sizeof(DBField));
return*this;
}

//定義排序字段數組類

typedefMSArray
<DBField>DBFieldArray;

classDBFile:publicfstream//DBF文件類
{

typedef
struct
{
unsigned
chardbfflag;
unsigned
chardate_n;
unsigned
chardate_y;
unsigned
chardate_r;
longrecords;
unsignedldb,lrd;
char_nul[20];
}DBFSTRUCT;

DBFSTRUCTstr;
char*buf;
DBFieldTmpField;
intfields;
longoldrecords;
intopenerror;
DBFieldArraydArray;
voidSetBuf();
voidInit();
voidSetFields(int);
voidWriteDelFlag(long,int='*');

public:

DBFile();
//調用Use(char*)
DBFile(constchar*);
//調用Use(char*,DBField*,int)
DBFile(constchar*,DBField*,int);
~DBFile();
//打開一個已存在文件;參數:文件名
voidUse(constchar*);
//用一字段數組建立新文件;參數:文件名,字段數組,字段數
voidUse(constchar*,DBField*,int);
//關閉文件
voidUse();
voidClose();
//返回記錄數
longRecords();
//返回記錄長度
intRecSize();
//返回文件頭結構長度
intTopSize();
//返回字段數
intFields();
//返回打開文件時的錯誤代碼,錯誤碼:
//0無錯誤
//1文件不存在
//2建立新文件失敗
//3建立文件時未設置字段
//4讀文件頭出錯或非DBF文件
//5寫文件頭出錯
//6內存不夠
intOpenError();
//把當前記錄內容讀到緩衝區
voidRead();
//將緩衝區內容寫到當前記錄
voidWrite();
//取一字段內容到字符串中;參數:字段名,字符串
char*Get(char*,char*);
//取一字段內容到字符串中;參數:字段序號(按字段名排過序),字符串
char*Get(unsigned,char*);
//將字符串內容輸出到字段中;參數:字段名,字符串
voidPut(char*,constchar*);
//將字符串內容輸出到字段中;參數:字段序號(按字段名排過序),字符串
voidPut(unsigned,constchar*);
//將一浮點數輸出到字段中;參數:,字段名,浮點數
voidPut(char*,double);
//將一浮點數輸出到字段中;參數:字段序號(按字段名排過序),浮點數
voidPut(unsigned,double);
//將緩衝區內容追加到文件尾;參數:追加標記(0空記錄)
voidAppend(int=0);
//將一字段內容轉換爲浮點數返回(未檢查字段類型);參數:字段名
doubleoperator[](char*);
//功能同上;參數:字段序號(按字段名排過序)
doubleoperator[](unsigned);
//移動文件記錄put指針;參數:記錄號
voidSeekp(long);
//移動文件記錄get指針;參數:記錄號
voidSeekg(long);
//將緩衝區內容輸出到文件;參數:記錄號
DBFile&operator<<(long);
//從文件中輸入內容到緩衝區中;參數:記錄號
DBFile&operator>>(long);
//返回緩衝區指針
char*Buf();
//在字段排序數組中查找字段,返回序號,未找到返回0X7FFF;參數:字段名
unsignedFindField(char*);
//返回字段排序數組
DBFieldArray&FieldArray();
//給記錄打上刪除標記
voidDelete(long);
//取消記錄的刪除標記
voidUnDelete(long);
//如記錄號在文件記錄範圍內返回TRUE,否則返回FALSE
intInRecords(long);

};

inlineDBFile::DBFile():dArray(
0,1)
{
Init();
}

inline
longDBFile::Records()
{
returnstr.records;
}

inline
intDBFile::RecSize()
{
returnstr.lrd;
}

inline
intDBFile::TopSize()
{
returnstr.ldb;
}

inline
intDBFile::Fields()
{
returnfields;
}

inline
char*DBFile::Buf()
{
returnbuf;
}

inlineDBFieldArray
&DBFile::FieldArray()
{
returndArray;
}

inline
voidDBFile::Use()
{
Close();
}

inlineDBFile::
~DBFile()
{
Close();
}

inline
intDBFile::OpenError()
{
returnopenerror;
}

inlineunsignedDBFile::FindField(
char*name)
{
strcpy(TmpField.name,strupr(name));
returndArray.Find(TmpField);
}

inline
voidDBFile::Read()
{
read(buf,str.lrd);
}

inline
voidDBFile::Write()
{
*buf=32;
write(buf,str.lrd);
}

inline
char*DBFile::Get(char*name,char*s)
{
returnGet(FindField(name),s);
}

inline
voidDBFile::Put(char*name,constchar*s)
{
Put(FindField(name),s);
}

inline
voidDBFile::Put(char*name,doubles)
{
Put(FindField(name),s);
}

inline
doubleDBFile::operator[](char*name)
{
returnatof(Get(name,str._nul));
}

inline
doubleDBFile::operator[](unsignedi)
{
returnatof(Get(i,str._nul));
}

inline
voidDBFile::Seekp(longrecnum)
{
seekp(recnum
*str.lrd+str.ldb);
}

inline
voidDBFile::Seekg(longrecnum)
{
seekg(recnum
*str.lrd+str.ldb);
}

inline
voidDBFile::Delete(longrecnum)
{
WriteDelFlag(recnum);
}

inline
voidDBFile::UnDelete(longrecnum)
{
WriteDelFlag(recnum,
32);
}

inline
intDBFile::InRecords(longrecnum)
{
return(recnum>=0&&recnum<str.records);
}

#endif

DEFile類的CPP文件:

//DBFILE.CPP

#include
"dbfio.hpp"
#include
<ctype.h>

voidDBField::SetValue(char*n,intt,intw,intd)
{
strcpy(name,strupr(n));
type
=toupper(t);
width
=w;
dec
=d;
}

voidDBFile::Init()
{
fields
=0;
buf
=0;
}

voidDBFile::SetFields(intn)
{
fields
=n;
if(n)
{
dArray.SetLimit(n);
buf
=newchar[str.lrd+1];
buf[
0]=32;
buf[str.lrd]
=0x1a;
if(!buf||!dArray.Items())
openerror
=6;
}
}

voidDBFile::Close()
{
if(oldrecords!=str.records)
{
seekp(
4);
write((
char*)&str.records,sizeof(unsignedlong));
oldrecords
=str.records;
}
close();
if(buf)
delete[]buf;
dArray.RemoveAll();
Init();
if(openerror)
setstate(ios::badbit);
}

char*DBFile::Get(unsignedi,char*s)
{
if(i<dArray.Count())
{
memcpy(s,
&buf[dArray[i].off],dArray[i].width);
s[dArray[i].width]
=0;
}
else
*s=0;
returns;
}

DBFile
&DBFile::operator>>(longrecnum)
{
if(InRecords(recnum))
{
Seekg(recnum);
Read();
}
else
memset(buf,
32,str.lrd);
return*this;
}

voidDBFile::WriteDelFlag(longrecnum,intFlag)
{
Seekp(recnum);
write((
char*)&Flag,1);
}

//DBFPUT.CPP

#include
"dbfio.hpp"
#include
<strstrea.h>
#include
<iomanip.h>
#include
<bcd.h>

voidDBFile::Put(unsignedi,constchar*s)
{
if(i<dArray.Count())
{
intflag=ios::left;
ostrstreamos(buf,str.lrd);
os.seekp(dArray[i].off);
if(dArray[i].type=='N'||dArray[i].type=='F')
flag
=ios::right;
os
<<setw(dArray[i].width)<<setiosflags(flag)<<s;
}
}

voidDBFile::Put(unsignedi,doubleval)
{
if(i<dArray.Count())
{
ostrstreamos(buf,str.lrd);
bcda(val,dArray[i].dec);
os.seekp(dArray[i].off);
os
<<setw(dArray[i].width)<<setiosflags(ios::right|ios::fixed)<<a;
}
}

voidDBFile::Append(intflag)
{
if(!flag)
memset(buf,
32,str.lrd);
Seekp(str.records);
Write();
str.records
++;
}

DBFile
&DBFile::operator<<(longrecnum)
{
if(InRecords(recnum))
{
Seekp(recnum);
Write();
}
else
Append(
1);
return*this;
}

//DBFUSE.CPP

#include
"dbfio.hpp"

DBFile::DBFile(
constchar*name):dArray(0,1)
{
Init();
Use(name);
}

voidDBFile::Use(constchar*name)
{
if(fields)
Close();
open(name,ios::
in|ios::out|ios::binary|ios::nocreate);
if(bad())
{
openerror
=1;
return;
}
openerror
=0;
read((
char*)&str,sizeof(DBFSTRUCT));
oldrecords
=str.records;
if(fail()||str.dbfflag!=3)
openerror
=4;
else
SetFields(str.ldb
/32-1);
if(!openerror)
{
DBFieldField;
for(inti=0;i<fields;i++)
{
read((
char*)&Field,sizeof(DBField));
dArray.Add(Field);
seekg(
32-sizeof(DBField),ios::cur);
}
seekg(
1,ios::cur);
if(fail())
openerror
=4;
}
if(openerror)
Close();
}

DBFile::DBFile(
constchar*name,DBField*fie,intn):dArray(0,1)
{
Init();
Use(name,fie,n);
}

voidDBFile::Use(constchar*name,DBField*fie,intn)
{
if(!fie||!n)
{
openerror
=3;
return;
}
if(fields)
Close();
openerror
=0;
str.lrd
=1;
for(inti=0;i<n;str.lrd+=fie[i].width,i++)
fie[i].off
=str.lrd;
str.dbfflag
=3;
str.date_n
=96;
str.date_y
=str.date_r=1;
str.ldb
=n*32+33;
memset(str._nul,
0,20);
open(name,ios::
in|ios::out|ios::binary|ios::trunc);
if(bad())
openerror
=2;
else
{
str.records
=oldrecords=0;
write((
char*)&str,sizeof(DBFSTRUCT));
SetFields(n);
if(!openerror)
{
for(inti=0;i<fields;i++)
{
write((
char*)&fie[i],sizeof(DBField));
write(str._nul,
32-sizeof(DBField));
dArray.Add(fie[i]);
}
i
=0x0d;
write((
char*)&i,1);
if(fail())
openerror
=5;
}
}
if(openerror)
Close();
}
DBFIle類所使用的動態數組模板類文件://MARRAY.HPP

#ifndef__MARRAY_HPP
#define__MARRAY_HPP

#include
<string.h>
#include
<iostream.h>

//無序直接數組類模板.用戶類中應定義默認構造函數和運算符==.

template
<classT>classMArray
{

protected:

char*items;//動態數組指針
intcount;//數組中對象個數
intlimit;//數組容量
intdelta;//數組增量
inttypesize;
MArray(){}
voidInit(int,int,int);
virtualT&Item(intindex)
{
return*(T*)&items[index*typesize];
}
virtualvoidLet(intindex,constT*t)
{
memmove(
&items[index*typesize],t,typesize);
}

public:

//構造函數.參數:數組容量(個);增加量
MArray(int,int=0);
~MArray();
voidSetLimit(int);
//移去一個對象,其後對象前移.參數:數組下標
voidRemove(int);
//移去指定位置及其後的所有對象;參數:數組下標
voidRemoveAll(int=0);
//增加對象到指定位置,其後對象後移,返回實際下標,出錯返回0x7fff.
//參數:數組下標;對象
intAddAt(int,constT&);
//增加對象到數組尾部,返回實際的數組下標,出錯返回0x7fff.參數:對象
intAdd(constT&);
//返回動態數組指針
char*Items();
//查找對象,返回對象下標,未找到返回0X7FFF.參數:對象
intFind(constT&);
//返回數組中的對象個數
intCount();
//返回數組容量大小
intArraySize();
//返回對象的內存長度
intObjectSize();
//返回數組下標所指的對象,下標超範圍時返回值不定

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章