📄 dbf.cpp
字号:
// DBF.cpp: implementation of the CDBF class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "DBReader.h"
#include "DBF.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
int qfind(INDEXTAB a[],const char * y,int n)/*二分法查找*/
{
int low,high,mid;
low=0;
high=n-1;
while(low<=high)
{
mid=(high+low)/2;
if(strcmp(a[mid].name,y)<0)
{
low=mid+1;
}
else if(strcmp(a[mid].name,y)>0)
{
high=mid-1;
}
else
return mid;
}
return -1;
}
int Compare(const void *a, const void *b)
{
return( strcmp (((INDEXTAB *)a)->name ,((INDEXTAB *)b)->name ) );
}
CDBF::CDBF()
{
pFields=NULL;
pIndexTable=NULL;
memset(mIndexName,0,255);
mCurIndex=0;
mCurRec=0;
mHeadLen=0;
mFieldNum=0;
mRecNum=0;
}
CDBF::~CDBF()
{
Close();
}
int CDBF::Open(CString sFileName,int mMode)
{
char cFileName[MAXCHAR];
strcpy(cFileName,(LPCTSTR)sFileName);
return Open(cFileName,mMode);
}
int CDBF::Open(char *mFileName, int mMode)
{
DBFHEAD mHead;
if(mFile.Open(mFileName, CFile::modeReadWrite | CFile::shareDenyNone) )
{
mFile.Read (&mHead,sizeof(DBFHEAD));
mHeadLen=mHead.headLength[1];
mHeadLen<<=8;
mHeadLen+=mHead.headLength[0];
//获得记录长度
mRecLen=mHead.recLength [1];
mRecLen<<=8;
mRecLen+=mHead.recLength [0];
mRecNum=mHead.recTotal [3];
mRecNum<<=8;
mRecNum+=mHead.recTotal [2];
mRecNum<<=8;
mRecNum+=mHead.recTotal [1];
mRecNum<<=8;
mRecNum+=mHead.recTotal [0];
mFieldTotalLen=mHeadLen-sizeof(DBFHEAD);
mFieldNum=mFieldTotalLen/sizeof(DBFFIELD);
pFields=(DBFFIELD*)calloc(mFieldTotalLen,1);//获取字段结构
mFile.Read (pFields,mFieldTotalLen);
return 1;
}
else
return 0;
}
int CDBF::Close()
{
if(pFields!=NULL)
{
free(pFields);
pFields=NULL;
}
if(pIndexTable!=NULL)
{
free(pIndexTable);
pIndexTable=NULL;
}
if(mFile.m_hFile!=0xFFFFFFFF)
mFile.Close ();
return 0;
}
int CDBF::ReadRec(CRecord * pBuf,BOOL *mDelFlag)
{
pBuf->Init (this);
mFile.Seek (mCurRec*mRecLen+mHeadLen ,0);
mFile.Read (pBuf->pData ,mRecLen);//读取一条记录
if(pBuf->pData[0]=='*')//获取删除标志
*mDelFlag=TRUE;
else
*mDelFlag=FALSE;
return mRecLen;
}
int CDBF::SeekRec(UINT mRecIndex)
{
if(mRecIndex>mRecNum-1)//到达文件底部
return -1;
mCurRec=mRecIndex;
return mCurRec;
}
int CDBF::LockRec()
{
DWORD i;
while(1)
{
try
{
mFile.LockRange (mCurRec*mRecLen+mHeadLen,mRecLen);
}
catch(...)
{
i=GetLastError();
if(i!=NO_ERROR)
{
Sleep(10);
continue;
}
}
break;
}
return 1;
}
int CDBF::UnLock()
{
mFile.UnlockRange (mCurRec*mRecLen+mHeadLen,mRecLen);
return 1;
}
int CDBF::FindField(char *mFieldName,UINT * mLen)
{
UINT i;
UINT len;
len=0;
for(i=0;i<mFieldNum;i++)
{
if(strcmp(mFieldName,(const char *)pFields[i].name)==0)
break;
len+=pFields[i].length;
}
if(i==mFieldNum)
{
*mLen=0;
return -1;
}
else
{
*mLen=pFields[i].length;
return len;
}
}
int CDBF::WriteRec(CRecord *pRecord)
{
mFile.Seek (mCurRec*mRecLen+mHeadLen ,0);
try
{
mFile.Write (pRecord->pData ,pRecord->mRecLen );//读取一条记录
return 1;
}
catch(...)
{
return 0;
}
}
//释放已经被删除记录的空间
int CDBF::Pack()
{
CRecord mRe;
unsigned char buf[4]={0};
UINT i,j,mUnDelNum;
BOOL DelFlag;
j=0;
mUnDelNum=0;
for(i=0;i<mRecNum;i++)
{
SeekRec(i);
ReadRec(&mRe,&DelFlag);
if(DelFlag==FALSE)
{
if(i!=j)
{
SeekRec(j);
WriteRec(&mRe);
}
j++;
}
}
mRecNum=j;
mFile.SetLength (mHeadLen+mRecNum*mRecLen);
buf[3]=mRecNum>>24;
buf[2]=(mRecNum>>16)&0xff;
buf[1]=(mRecNum>>8)&0xff;
buf[0]=mRecNum&0xFF;
mFile.Seek (4,0);
mFile.Write (buf,4);
CreateIndex(mIndexName);
return 0;
}
//逻辑删除记录
int CDBF::Delete(UINT mRecIndex)
{
CRecord mRe;
BOOL DelFlag;
SeekRec(mRecIndex);
ReadRec(&mRe,&DelFlag);
if(DelFlag==FALSE)
{
mRe.SetDel ();
WriteRec(&mRe);
}
return 0;
}
//恢复被逻辑删除的记录
int CDBF::UnDelete(UINT mRecIndex)
{
CRecord mRe;
BOOL DelFlag;
SeekRec(mRecIndex);
ReadRec(&mRe,&DelFlag);
if(DelFlag==TRUE)
{
mRe.SetUndel ();
WriteRec(&mRe);
}
return 0;
}
//删除全部记录并释放空间
int CDBF::Zap()
{
try
{
char buf[4]={0};
mFile.SetLength (mHeadLen);
mRecNum=0;
mFile.Seek (4,0);
mFile.Write (buf,4);
CreateIndex(mIndexName);
return 1;
}
catch(...)
{
return 0;
}
}
int CDBF::Append(CRecord *mRecord)
{
unsigned char buf[4]={0};
INDEXTAB * p;
mCurRec=mRecNum;
if(WriteRec(mRecord))
{
mRecNum++;
buf[3]=mRecNum>>24;
buf[2]=(mRecNum>>16)&0xff;
buf[1]=(mRecNum>>8)&0xff;
buf[0]=mRecNum&0xFF;
mFile.Seek (4,0);
mFile.Write (buf,4);
p=(INDEXTAB*)calloc(sizeof(INDEXTAB)*mRecNum,1);
memcpy(p,pIndexTable,sizeof(INDEXTAB)*(mRecNum-1));
free(pIndexTable);
pIndexTable=p;
::qsort (p,mRecNum,sizeof(INDEXTAB),Compare);
mCurIndex=0;
return 1;
}
return 0;
}
int CDBF::CreateIndex(unsigned char *mFieldName)
{
CRecord mRe;
unsigned char buf[255]={0};
INDEXTAB *p;
BOOL DelFlag;
UINT mLen;
UINT i;
if(IsExistField((char*)mFieldName)==FALSE)//没有这个字段
return 0;
memset(mIndexName,0,255);
memcpy(mIndexName,mFieldName,strlen((char*)mFieldName));
if(pIndexTable!=NULL)
free(pIndexTable);
pIndexTable=(INDEXTAB *)calloc(sizeof(INDEXTAB)*mRecNum,1);
p=(INDEXTAB *)(pIndexTable);
for(i=0;i<mRecNum;i++)
{
SeekRec(i);
ReadRec(&mRe,&DelFlag);
memset(buf,0,255);
if(mRe.GetField ((char *)mFieldName,buf,&mLen)==NULL)
return -2;//字段不存在
memcpy(p[i].name ,buf,strlen((char *)buf));
p[i].index =i;
p[i].mDelFlag =DelFlag;
}
mCurIndex=0;
::qsort (p,mRecNum,sizeof(INDEXTAB),Compare);
return 1;
}
//参数说明:mField 字段名称 mValue字段的值 mDelFlag是否忽略删除的记录 :true 不忽略
int CDBF::FindRecord(unsigned char *mField, unsigned char *mValue,BOOL mDelFlag)
{
CRecord mRe;
unsigned char buf[255]={0};
BOOL DelFlag;
UINT mLen;
int i,j;
if(strcmp((char *)mField,(char *)mIndexName)==0)
{
i=qfind((INDEXTAB *)pIndexTable+mCurIndex,(char*)mValue,mRecNum-mCurIndex);
if(i>=0)//找到了
{
i+=mCurIndex;
for(j=i;j>=mCurIndex;j--)//找到第一个匹配记录
{
if(strcmp(pIndexTable[j].name ,(char *)mValue)!=0)
break;
}
if(mDelFlag==FALSE)//如果过滤删除的记录
{
for(i=j;i>mRecNum;i++)
{
if(strcmp(pIndexTable[i].name ,(char *)mValue)!=0)
return -1;
else
{
if(pIndexTable[i].mDelFlag ==FALSE)
break;
}
}
mCurIndex=i+1;
SeekRec(pIndexTable[j+1].index);
return pIndexTable[i].index ;
}
else
{
mCurIndex=j+2;
SeekRec(pIndexTable[j+1].index);
return pIndexTable[j+1].index ;
}
}
return -1;
}
else
for(i=mCurRec;i<mRecNum;i++)
{
SeekRec(i);
ReadRec(&mRe,&DelFlag);
if(DelFlag==TRUE)
{
if(mDelFlag==FALSE)//过滤删除的记录
{
continue;
}
}
memset(buf,0,255);
if(mRe.GetField ((char *)mField,buf,&mLen)==NULL)
return -2;//字段不存在
if(strcmp((char *)buf,(char *)mValue)==0)
break;
}
if(i==mRecNum)
return -1;//没有找到匹配的记录
return i;
}
BOOL CDBF::IsExistField(char *mFieldName)
{
UINT i;
for(i=0;i<mFieldNum;i++)
{
if(strcmp(mFieldName,(const char *)pFields[i].name)==0)
break;
}
if(i==mFieldNum)
return FALSE;
else
return TRUE;
}
int CDBF::UpdateRec(char *mFieldName, unsigned char *mValue, CRecord *mRe,BOOL mDelFlag)
{
int i,j;
if(IsExistField(mFieldName)==FALSE)
return -1;
j=0;
while(1)
{
i=FindRecord((unsigned char *)mFieldName,mValue,mDelFlag);
if(i<0)
{
if(j>0)
{
CreateIndex((unsigned char *)mIndexName);
return j;
}
else
return 0;
}
else
{
SeekRec(i);
WriteRec(mRe);
j++;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -