十几年前,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;
unsignedcharwidth;
unsignedchardec;
DBField()
{
memset(this,0,sizeof(DBField));
}
intoperator==(constDBField&);
intoperator<(constDBField&);
DBField&operator=(constDBField&);
//设置字段.参数:名称,类型,宽度,小数位
voidSetValue(char*,int,int,int=0);
};
inlineintDBField::operator==(constDBField&d)
{
return!strcmp(name,d.name);
}
inlineintDBField::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文件类
{
typedefstruct
{
unsignedchardbfflag;
unsignedchardate_n;
unsignedchardate_y;
unsignedchardate_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();
}
inlinelongDBFile::Records()
{
returnstr.records;
}
inlineintDBFile::RecSize()
{
returnstr.lrd;
}
inlineintDBFile::TopSize()
{
returnstr.ldb;
}
inlineintDBFile::Fields()
{
returnfields;
}
inlinechar*DBFile::Buf()
{
returnbuf;
}
inlineDBFieldArray&DBFile::FieldArray()
{
returndArray;
}
inlinevoidDBFile::Use()
{
Close();
}
inlineDBFile::~DBFile()
{
Close();
}
inlineintDBFile::OpenError()
{
returnopenerror;
}
inlineunsignedDBFile::FindField(char*name)
{
strcpy(TmpField.name,strupr(name));
returndArray.Find(TmpField);
}
inlinevoidDBFile::Read()
{
read(buf,str.lrd);
}
inlinevoidDBFile::Write()
{
*buf=32;
write(buf,str.lrd);
}
inlinechar*DBFile::Get(char*name,char*s)
{
returnGet(FindField(name),s);
}
inlinevoidDBFile::Put(char*name,constchar*s)
{
Put(FindField(name),s);
}
inlinevoidDBFile::Put(char*name,doubles)
{
Put(FindField(name),s);
}
inlinedoubleDBFile::operator[](char*name)
{
returnatof(Get(name,str._nul));
}
inlinedoubleDBFile::operator[](unsignedi)
{
returnatof(Get(i,str._nul));
}
inlinevoidDBFile::Seekp(longrecnum)
{
seekp(recnum*str.lrd+str.ldb);
}
inlinevoidDBFile::Seekg(longrecnum)
{
seekg(recnum*str.lrd+str.ldb);
}
inlinevoidDBFile::Delete(longrecnum)
{
WriteDelFlag(recnum);
}
inlinevoidDBFile::UnDelete(longrecnum)
{
WriteDelFlag(recnum,32);
}
inlineintDBFile::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:
分享到:
相关推荐
sjshq.dbf-------用于测试服务器端原代码----股票实时行情---------深圳dbf
功能:操作DBF文件的C++代码,可以创建DBF文件、读取DBF文件、写入DBF文件、拷贝DBF文件的结构 环境:需要C++11和BOOST库,需要设置环境变量BOOST_HOME指向BOOST的根目录 例子:见main.cpp
深入剖析dbf文件,以文件形式读取dbf文件. 不需要安装Visual Foxpro驱动,非常值得学习
dbf-jdbc-wisecoders,JAVA 读写DBF文件工具包
200805月,最近写了一个操作dbf文件的c++类,可以读、追加、删除、搜索,我觉得代码写得比较清晰,对函数写了中文注释。但是功能还不强大,只支持char类型的字段,不能创建新dbf文件。希望对大家有帮助,也希望大家...
c++ DBF 读取数据库DBF格式,实例代码 c++ DBF 读取数据库DBF格式,实例代码
操纵DBF数据库文件的C++类及库,老外的东西。
DBF读写文件 C++ 查找 一次查找一个 一次查找多个 附带测试文件
DBF解压程序.适合大多数DBF数据文件
arcgis10.2以后,shp文件属性表中文会有乱码的情况(该情况通常在原有低版本arcgis升级版本后才出现),解决属性表乱码的插件
Kettle8.0清洗交易所DBF文件数据 Kettle8.0清洗交易所DBF文件数据 Kettle8.0清洗交易所DBF文件数据
行业分类-设备装置-DBF数据导出平台及其导出方法.zip
Java library for fast reading/writing DBF-files. Build from sources For build project from sources you need to run gradlew script from the root directory: git clone git@github.com:jamel/dbf.git cd dbf...
一个用来操作DBF的类,非常好用,找了好久才找到,希望能帮助你
show2003.dbf----用于测试服务器端源代码-------2017年之前股票实时行情交易所格式
ArcGIS默认dbf代码页-设置为UTF-8,解决有需要将gdb导出成shape file并将字符集设置成Utf-8以避免中文乱码的情况。
VC操作DBF数据库文件的类,用于读写dbf文件
精彩编程与编程技巧-DBF文件转为MDB文件的方法 ...
使用Day2Dbf工具指定行情软件所在地址,自动导出历史数据到dbf文件。
就是武汉大学的一个考试的题目,要求用C++写dbf3