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

C++老代码 -- DBF数据文件操作类DBFile

阅读更多

十几年前,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();
//返回数组下标所指的对象,下标超范围时返回值不定
Tcolor:
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics