⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dbf.cpp

📁 一个DB文件读取工具,最终转换CSV文件的代码.. 很有参考价值 作者:tanis
💻 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 + -