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

📄 dbfop.cpp

📁 一个操作DBF格式文件的类
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/************************************************************************
  DBFOP for C++ V1.00 ,1995.1.10
  Develop by John,Liao
  Modified by Zhanghao. 1998.05.18

  This Module include the C++ headfile dbfop.hpp,
  and C++ resource file dbfop.cpp.

  This module is develop for use DBF(DBASEIII,DBASEII,MFOXBASE,FOXPRO 2.x)
  and IDX(MFOXBASE).but use IDX only allow read or change the field that
  isn't key word.
  Support netware share .flielock,fileunlock,recordlock,recordunlock.
*************************************************************************/
/* -----------------------------------------------------------------------
  The class DBF is interface to custom,all function that given
  can be invoked by use the class DBF.
  ------------------------------------------------------------------------
  1995.7.29 Change file option fxxx to xxx like _fsopen replace with sopen
  1995.7.31 Change dowith option when type='N'
  1995.7.31 Add option DBF::append(),DBF::clear();
  1998.5.18 Add Foxpro 2.x DBF process.
-------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <share.h>
#include <string.h>
#include <io.h>
#include <dos.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <share.h>
#include <ctype.h>
#include "dbfop.hpp"
static INT2 ccc(CHAR *,INT2,INT2);
INT2 ccc(CHAR * ptsr,INT2 len,INT2 bit)
{
	CHAR temp1[30],temp11[30],i1;
	CHAR temp2[30],temp22[30],i2;
	INT2  tempi,i;
	CHAR * ps,*ps1;
	for(ps1=ptsr;(*ps1==' ')&&(*ps1!='\x0');ps1++);
	ps=strchr(ps1,'.');
	if(ps==NULL){  // NOT HAVE '.'
		strcpy(temp1,ps1);
		temp2[0]='\x0';
	}else{
		*ps='\x0';
		strcpy(temp1,ps1);
		ps++;
		strcpy(temp2,ps);
	}
	i1=(short)(len-(bit?(bit+1):0));
	if((short)strlen(temp1) > i1){
		strncpy(temp11,temp1,i1);
		temp11[i1]='\x0';
	}else{
		tempi=(INT2)(i1-strlen(temp1));
		for(i=0;i<tempi;i++) temp11[i]=' ';
		strcpy(temp11+tempi,temp1);
	}
	// ------------------------------------------
	if(bit>0){
		if((short)strlen(temp2) > bit){
			strncpy(temp22,temp2,bit);
			temp22[bit]='\x0';
		}else{
			i2=(short)strlen(temp2);
			tempi=(INT2)(bit-strlen(temp2));
			strcpy(temp22,temp2);
			for(i=0;i<tempi;i++) (temp22+i2)[i]='0';
			temp22[bit]='\x0';
		}
	}
	strcpy(ptsr,temp11);
	if(bit!=0){
		strcat(ptsr,".");
		strcat(ptsr,temp22);
	}
	return 0;
}
INT2 IDX_BLOCK::skip()
{
	if(curp>=(INT2)items-1){
		return -2;
	}
	curp++;
	return 0;
}
INT2 IDX_BLOCK::find(CHAR * key)
{
	INT2 compi=keylen;
	CHAR *p;
	INT2 RetCode,i;
	if((short)strlen(key)<keylen)
		compi=(INT2)strlen(key);
	for(i=0,p=buff+12;i<items;i++,p+=keylen+4){
		RetCode=(INT2)strncmp(key,p,compi);
		if(RetCode==0)     // Founded this key
			if(flag>=2){    // .and. this is a leaf or leaf&root node
				curp=i;
				return 0;    // Founded ,OK return to master
			}else{          // .and. this is a frame or root node
				curp=i;
				return -10;   // This is a ROOT,Maybe in gaven BLOCK
			}
		if(RetCode<0){    //if the key < curent key in idx file
			if(flag<2){   //and this is FRAME or ROOT node
				curp=i;    //in FRAME or ROOT node key is MAXKEY in given node
				return -10;//This is a ROOT,Maybe in gaven BLOCK
			}
		}
	}
	return -3;  // Maybe in NextBlock
}
IDX::IDX()
{
	Installed=0;
	//fp=NULL;
	handle=-1;
	rootpos=blocks=0l;
	key_len=0;
	return ;
}
IDX::~IDX()
{
	if(this->handle!=-1){
		close(handle);
		handle=-1;
	}
}
// open function open the idx file
INT2 IDX::open(CHAR * filename)
{
	CHAR buff[30];
	// fp=_fsopen(filename,"rb",SH_DENYNONE);
    // change by liaoj int 1999.3.22
    handle=(INT2)sopen(filename,O_RDONLY|O_BINARY|O_DENYNONE,SH_DENYNONE,S_IREAD);
    /*
	handle=sopen(filename,O_RDWR|O_BINARY|O_DENYNONE,
					   SH_DENYNONE,S_IREAD|S_IWRITE);
    */
	// if(fp==NULL) return -1;
	if(handle==-1) return -1;
	if(lseek(handle,0,SEEK_SET)!=0) return -1;
	if(read(handle,buff,30)!=30) return -1;
	rootpos=*(UINT4 *)buff;
	blocks=*(UINT4 *)(buff+8);
	key_len=*(INT2 *)(buff+12);
	block.SetKeyLen(key_len);
	block.ReadBlock(this->handle,rootpos);
	while(block.GetFlag()<2){
	   block.ReadBlock(this->handle,block.GetResult());
	}
	GoHome();
	return 0;
}
INT2 IDX::Prev()
{
	UINT4 PrevBlock;
	if(block.Prev()!=0){
		PrevBlock=block.GetPrev();
		if(PrevBlock==0xffffffffl){
			return -1;
		}
		block.ReadBlock(this->handle,(INT4)PrevBlock);
		block.End();
	}
	return 0;
}
INT2 IDX::Next()
{
	UINT4 NextBlock;
	if(block.Next()!=0){  // Is already in the last node in this block
		NextBlock=block.GetNext();
		if(NextBlock==0xffffffffl){
			return -2;
		}
		block.ReadBlock(this->handle,(INT4)NextBlock);
		block.Home();
	}
	return 0;
}
INT2 IDX::Find(CHAR * key)
{
	INT2 RetCode;
	block.ReadBlock(this->handle,rootpos);
	for(;;){
	    RetCode=block.find(key);
	    switch(RetCode){
		    case 0:
                       return 0;
		    case -1:
		       return -1;
		    case -2:
		       if(block.GetPrev()==(UINT4)0xffffffffl){
		          return -1;
		       }else{
			  block.ReadBlock(this->handle,block.GetPrev());
		       }
		       break;
		    case -3:
			if(block.GetNext()==(UINT4)0xffffffffl){
				     return -1;
			}else {
				     block.ReadBlock(this->handle,block.GetNext());
			}
			break;
		    case -10:
				       block.ReadBlock(this->handle,block.GetResult());
				       break;
                    default:
				     // -------------------------------------------------
				     // Fatal Error :: return code is not allow
				     //                in class IDX_BLOCK::find(CHAR * );
				     // -------------------------------------------------
				     break;
	    }
	}
}
INT2 IDX::Skip()
{
	return Next();
}
INT2  IDX::GoHome()
{
	while(block.GetPrev()!=(UINT4)0xffffffffl){
		   block.ReadBlock(this->handle,block.GetPrev());
	};
	block.Home();
	return 0;
}
INT2 IDX::GoEnd()
{
	while(block.GetNext()!=(UINT4)0xffffffffl){
		   block.ReadBlock(this->handle,block.GetNext());
	};
	block.End();
	return 0;
}
UINT4 IDX_BLOCK::GetResult()
{
	CHAR tf[5];
	CHAR * p=buff+12+curp*(keylen+4);
	p+=keylen;
	tf[3]=p[0];tf[2]=p[1];tf[1]=p[2];tf[0]=p[3];
	return *(UINT4 * )tf;
}
//INT2 IDX_BLOCK::ReadBlock(FILE * fp,UINT4 pos)
INT2 IDX_BLOCK::ReadBlock(INT2 handle,UINT4 pos)
{
	 // fseek(fp,pos,SEEK_SET);
	lseek(handle,pos,SEEK_SET);
	 // fread(buff,512l,1,fp);
	read(handle,buff,512);
	flag=buff[0];
	count=buff[1];
	items=buff[2];
	prev=*(UINT4 *)(buff+4);
	next=*(UINT4 *)(buff+8);
	curp=0;
	return 0;
}

//------------------Next is DBF ----------------------
DBF::DBF()
{
	Installed=0;
	First=NULL;
	pIDX=NULL;
	handle=-1;
	buff=NULL;
	// ---------------------------------
	SwapBuffer=NULL;
	MaxRecNum=0;
	CurRecNum=0;
	// --------------------------------
	current_recno=record_no=0l;
	record_len=0;
	Name[0]='\x0';
	changeflag=0;
	m_errno=0;
	fieldvalue=NULL;
    pFIELD = NULL;
}
DBF::~DBF()
{
	if(First!=NULL){
		delete First;
		First=NULL;
	}
	if(SwapBuffer!=NULL) delete SwapBuffer;
	SwapBuffer=NULL;
	MaxRecNum=0;
	CurRecNum=0;
	if(pIDX!=NULL){
		delete First;
		pIDX=NULL;
	}
	if(handle!=-1){ // this
		::close(handle);
		handle=-1;
	}

	if(buff!=NULL){
		delete buff;
		buff=NULL;
	}
	if(fieldvalue!=NULL){
		delete fieldvalue;
		fieldvalue=NULL;
	}
	return;
}
INT2 DBF::Clear()
{
	memset(buff,' ',record_len);
	return 0;
}
INT2 DBF::AppendBlank()
{
	CHAR tempbuf[100];
	UINT4  temp_recno;
	INT2 i;
	INT4 offset;
	if(!Installed){  // Not open this file
		m_errno=ClassNotInit;
		return ClassNotInit;
	}

	if(lseek(handle,0l,SEEK_SET)!=0){
		m_errno=SeekFileError;
		return SeekFileError;
	}
	if(read(handle,tempbuf,8)!=8){
		m_errno=ReadFileError;
		return ReadFileError;
	}
	temp_recno=++(*(UINT4*)(tempbuf+4));// recordnum+1;
	if(lseek(handle,0l,SEEK_SET)!=0){
		m_errno=SeekFileError;
		return m_errno;
	}
	if(write(handle,tempbuf,8)!=8){
		m_errno=WriteFileError;
		return m_errno;
	}
	offset=(INT4)head_len+(temp_recno-1l)*record_len;
	lseek(handle,offset,SEEK_SET);
	for(i=0;i<(short)record_len;i++)  // fputc(0x20,fp); // FILL BLANK
		write(handle," ",1);
	write(handle,"\x1a",1);
	this->ReOpen();
	this->GoTo(temp_recno);
	return 0;
}
INT2 DBF::Append()
{
	CHAR tempbuf[100];
	UINT4  temp_recno;
	INT4 offset;
	if(!Installed){  // Not open this file
		errno=ClassNotInit;
		return ClassNotInit;
	}
	if(lseek(handle,0l,SEEK_SET)!=0){
		errno=SeekFileError;
		return SeekFileError;
	}
	if(read(handle,tempbuf,8)!=8){
		errno=ReadFileError;
		return m_errno;
	}
	temp_recno=++(*(UINT4*)(tempbuf+4));// recordnum+1;
	if(lseek(handle,0l,SEEK_SET)!=0){
		errno=SeekFileError;
		return m_errno;
	}
	if(write(handle,tempbuf,8)!=8){
		errno=WriteFileError;
		return m_errno;
	}
	offset=(INT4)head_len+(temp_recno-1l)*record_len;
	if(lseek(handle,offset,SEEK_SET)!=offset){
		errno=SeekFileError;
		return m_errno;
	}
	write(handle,buff,(UINT2)record_len);
	write(handle,"\x1a",1);
	this->ReOpen();
	this->GoTo(temp_recno);
	return 0;
}

INT2 DBF::dbf_wbuff()
{
	//CHAR tempbuf[100];
	INT4 offset;
	offset=(INT4)head_len+(current_recno-1l)*record_len;
	if(current_recno<=0){
		errno=RecordOutOfRange;
		return m_errno;
	}
	if(changeflag==0){
		errno=DBFOK;
		return DBFOK;
	}
	if(lseek(handle,offset,SEEK_SET)!=offset){
		errno=SeekFileError;
		return m_errno;
	}
	if((UINT2)write(handle,buff,(UINT2)record_len)!=(UINT2)record_len){
		errno=WriteFileError;
		return m_errno;
	}
	errno=DBFOK;
	return DBFOK;
}

INT2 DBF::dbf_buff()
{
	INT4 offset=(INT4)head_len+(current_recno-1l)*record_len;
	if(current_recno<=0){
		errno=RecordOutOfRange;
		return m_errno;
	}
	if(lseek(handle,offset,SEEK_SET)!=offset){
		errno=SeekFileError;
		return m_errno;
	}
	if(::eof(handle)){
		errno=SeekFileError;
		return m_errno;
	}
	if((UINT2)read(handle,buff,(UINT2)record_len)!=(UINT2)record_len){
		errno=ReadFileError;
		return m_errno;
	}
	changeflag=0;
	errno=0;
	return 0;
}
INT2 DBF::Zap()
{
	CHAR tempbuf[100];
	if(!Installed){  // Not open this file
		errno=ClassNotInit;
		return m_errno;
	}
	lseek(handle,0l,SEEK_SET);
	//if(fread(tempbuf,32l,1l,fp)!=1){
	if(read(handle,tempbuf,32)!=32){
		this->Close();
		errno=NotDBFFile;
		return m_errno;
	}
	*(UINT4 *)(tempbuf+4)=0l; // record_no
	if(chsize(handle,head_len)!=0){
		// ------------------------
		errno=ChsizeFileError;
		return m_errno;
	}
	lseek(handle,0l,SEEK_SET);
	if(write(handle,tempbuf,32)!=32){
		//this->close();
		errno=WriteFileError;
		return WriteFileError;
	}
	lseek(handle,0l,SEEK_END);
	write(handle,"\x1a\x0",2);
	MaxRecNum=0;
	CurRecNum=0;
	lock_flag=0;
	ReOpen();
        m_errno=DBFOK;
	return m_errno;
}
INT2 DBF::Open(CHAR * filename,INT2 OpenMode_Par,INT2 DBFType_Par)
{
	CHAR tempbuf[100];
	INT2  i,j,FieldOffset;
	struct FIELD * tpf;

	if(Installed){
		this->Close();
	}
	strcpy(Name,filename);
    OpenMode=OpenMode_Par;
    DBFType=DBFType_Par;

    if(OpenMode==ReadWrite){
        handle=(INT2)sopen(Name,O_RDWR|O_BINARY|O_DENYNONE,SH_DENYNONE,S_IREAD|S_IWRITE);
    }else{
        handle=(INT2)sopen(Name,O_RDONLY|O_BINARY|O_DENYNONE,SH_DENYNONE,S_IREAD);
    }

	if(handle==-1){
		errno=FileOpenFailure;
		return m_errno;
	}

	lseek(handle,0l,SEEK_SET);

	if(read(handle,tempbuf,32)!=32){
		this->Close();
		errno=ReadFileError;
		return m_errno;
	}
	record_no=*(UINT4 *)(tempbuf+4);
	head_len=*(UINT2 *)(tempbuf+8);
	//head_len=tempbuf[8];
	//head_len+=tempbuf[9]<<8;

	record_len=*(UINT2*)(tempbuf+10);
	fieldnum=(INT2)((head_len)/32-1);
        // need automatic detect the dbf file type is foxbase or clipper
        if(DBFType==AutoDetect){
          if((head_len-1)%32==0)
             DBFType=Foxbase;
          else
             DBFType=Clipper;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -