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 "

const int

DB_FieNameSize
= 11 ;

class DBField // DBF文件的字段类
{

public :

char name[DB_FieNameSize];
char type;
int off;
int nul;
unsigned
char width;
unsigned
char dec;
DBField()
{
memset(
this , 0 , sizeof (DBField));
}
int operator == ( const DBField & );
int operator < ( const DBField & );
DBField
& operator = ( const DBField & );
// 设置字段.参数:名称,类型,宽度,小数位
void SetValue( char * , int , int , int = 0 );
};

inline
int DBField:: operator == ( const DBField & d)
{
return ! strcmp(name,d.name);
}

inline
int DBField:: operator < ( const DBField & d)
{
return strcmp(name,d.name) < 0 ? 1 : 0 ;
}

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

// 定义排序字段数组类

typedefMSArray
< DBField > DBFieldArray;

class DBFile: public fstream // DBF文件类
{

typedef
struct
{
unsigned
char dbfflag;
unsigned
char date_n;
unsigned
char date_y;
unsigned
char date_r;
long records;
unsignedldb,lrd;
char _nul[ 20 ];
}DBFSTRUCT;

DBFSTRUCTstr;
char * buf;
DBFieldTmpField;
int fields;
long oldrecords;
int openerror;
DBFieldArraydArray;
void SetBuf();
void Init();
void SetFields( int );
void WriteDelFlag( long , int = ' * ' );

public :

DBFile();
// 调用Use(char*)
DBFile( const char * );
// 调用Use(char*,DBField*,int)
DBFile( const char * ,DBField * , int );
~ DBFile();
// 打开一个已存在文件;参数:文件名
void Use( const char * );
// 用一字段数组建立新文件;参数:文件名,字段数组,字段数
void Use( const char * ,DBField * , int );
// 关闭文件
void Use();
void Close();
// 返回记录数
long Records();
// 返回记录长度
int RecSize();
// 返回文件头结构长度
int TopSize();
// 返回字段数
int Fields();
// 返回打开文件时的错误代码,错误码:
// 0无错误
// 1文件不存在
// 2建立新文件失败
// 3建立文件时未设置字段
// 4读文件头出错或非DBF文件
// 5写文件头出错
// 6内存不够
int OpenError();
// 把当前记录内容读到缓冲区
void Read();
// 将缓冲区内容写到当前记录
void Write();
// 取一字段内容到字符串中;参数:字段名,字符串
char * Get( char * , char * );
// 取一字段内容到字符串中;参数:字段序号(按字段名排过序),字符串
char * Get(unsigned, char * );
// 将字符串内容输出到字段中;参数:字段名,字符串
void Put( char * , const char * );
// 将字符串内容输出到字段中;参数:字段序号(按字段名排过序),字符串
void Put(unsigned, const char * );
// 将一浮点数输出到字段中;参数:,字段名,浮点数
void Put( char * , double );
// 将一浮点数输出到字段中;参数:字段序号(按字段名排过序),浮点数
void Put(unsigned, double );
// 将缓冲区内容追加到文件尾;参数:追加标记(0空记录)
void Append( int = 0 );
// 将一字段内容转换为浮点数返回(未检查字段类型);参数:字段名
double operator []( char * );
// 功能同上;参数:字段序号(按字段名排过序)
double operator [](unsigned);
// 移动文件记录put指针;参数:记录号
void Seekp( long );
// 移动文件记录get指针;参数:记录号
void Seekg( long );
// 将缓冲区内容输出到文件;参数:记录号
DBFile & operator << ( long );
// 从文件中输入内容到缓冲区中;参数:记录号
DBFile & operator >> ( long );
// 返回缓冲区指针
char * Buf();
// 在字段排序数组中查找字段,返回序号,未找到返回0X7FFF;参数:字段名
unsignedFindField( char * );
// 返回字段排序数组
DBFieldArray & FieldArray();
// 给记录打上删除标记
void Delete( long );
// 取消记录的删除标记
void UnDelete( long );
// 如记录号在文件记录范围内返回TRUE,否则返回FALSE
int InRecords( long );

};

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

inline
long DBFile::Records()
{
return str.records;
}

inline
int DBFile::RecSize()
{
return str.lrd;
}

inline
int DBFile::TopSize()
{
return str.ldb;
}

inline
int DBFile::Fields()
{
return fields;
}

inline
char * DBFile::Buf()
{
return buf;
}

inlineDBFieldArray
& DBFile::FieldArray()
{
return dArray;
}

inline
void DBFile::Use()
{
Close();
}

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

inline
int DBFile::OpenError()
{
return openerror;
}

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

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

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

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

inline
void DBFile::Put( char * name, const char * s)
{
Put(FindField(name),s);
}

inline
void DBFile::Put( char * name, double s)
{
Put(FindField(name),s);
}

inline
double DBFile:: operator []( char * name)
{
return atof(Get(name,str._nul));
}

inline
double DBFile:: operator [](unsignedi)
{
return atof(Get(i,str._nul));
}

inline
void DBFile::Seekp( long recnum)
{
seekp(recnum
* str.lrd + str.ldb);
}

inline
void DBFile::Seekg( long recnum)
{
seekg(recnum
* str.lrd + str.ldb);
}

inline
void DBFile::Delete( long recnum)
{
WriteDelFlag(recnum);
}

inline
void DBFile::UnDelete( long recnum)
{
WriteDelFlag(recnum,
32 );
}

inline
int DBFile::InRecords( long recnum)
{
return (recnum >= 0 && recnum < str.records);
}

#endif

DEFile类的CPP文件:

// DBFILE.CPP

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

void DBField::SetValue( char * n, int t, int w, int d)
{
strcpy(name,strupr(n));
type
= toupper(t);
width
= w;
dec
= d;
}

void DBFile::Init()
{
fields
= 0 ;
buf
= 0 ;
}

void DBFile::SetFields( int n)
{
fields
= n;
if (n)
{
dArray.SetLimit(n);
buf
= new char [str.lrd + 1 ];
buf[
0 ] = 32 ;
buf[str.lrd]
= 0x1a ;
if ( ! buf || ! dArray.Items())
openerror
= 6 ;
}
}

void DBFile::Close()
{
if (oldrecords != str.records)
{
seekp(
4 );
write((
char * ) & str.records, sizeof (unsigned long ));
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 ;
return s;
}

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

void DBFile::WriteDelFlag( long recnum, int Flag)
{
Seekp(recnum);
write((
char * ) & Flag, 1 );
}

// DBFPUT.CPP

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

void DBFile::Put(unsignedi, const char * s)
{
if (i < dArray.Count())
{
int flag = 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;
}
}

void DBFile::Put(unsignedi, double val)
{
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;
}
}

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

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

// DBFUSE.CPP

#include
" dbfio.hpp "

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

void DBFile::Use( const char * 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 ( int i = 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(
const char * name,DBField * fie, int n):dArray( 0 , 1 )
{
Init();
Use(name,fie,n);
}

void DBFile::Use( const char * name,DBField * fie, int n)
{
if ( ! fie || ! n)
{
openerror
= 3 ;
return ;
}
if (fields)
Close();
openerror
= 0 ;
str.lrd
= 1 ;
for ( int i = 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 ( int i = 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
< class T > class MArray
{

protected :

char * items; // 动态数组指针
int count; // 数组中对象个数
int limit; // 数组容量
int delta; // 数组增量
int typesize;
MArray(){}
void Init( int , int , int );
virtual T & Item( int index)
{
return * (T * ) & items[index * typesize];
}
virtual void Let( int index, const T * t)
{
memmove(
& items[index * typesize],t,typesize);
}

public :

// 构造函数.参数:数组容量(个);增加量
MArray( int , int = 0 );
~ MArray();
void SetLimit( int );
// 移去一个对象,其后对象前移.参数:数组下标
void Remove( int );
// 移去指定位置及其后的所有对象;参数:数组下标
void RemoveAll( int = 0 );
// 增加对象到指定位置,其后对象后移,返回实际下标,出错返回0x7fff.
// 参数:数组下标;对象
int AddAt( int , const T & );
// 增加对象到数组尾部,返回实际的数组下标,出错返回0x7fff.参数:对象
int Add( const T & );
// 返回动态数组指针
char * Items();
// 查找对象,返回对象下标,未找到返回0X7FFF.参数:对象
int Find( const T & );
// 返回数组中的对象个数
int Count();
// 返回数组容量大小
int ArraySize();
// 返回对象的内存长度
int ObjectSize();
// 返回数组下标所指的对象,下标超范围时返回值不定
T color:
分享到:
评论

你可能感兴趣的:(数据结构,ios,C++,c,C#)