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

📄 dbf.cpp

📁 读写DBF文件的库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "dbf.h"
#include "xntoy.h"

//*************************************************************
//	DBF读写类库跨平台版本,在windows、linux、Sco下编译通过。
//	修改:袁斌	
//	oldworm@21cn.com
//	http://yb.nos.com.cn/index.html
//	时间:2000年4月11日
//	bug report: 内部->yb@compagis.com	
//				外部->oldworm@21cn.com
//
//	主要修改内容:
//	一、速度方面的修改。
//	1、将原先通过多个sprintf、sscanf等写一条记录的方式改为
//	通过调用xntoy系列函数取代,速度提高不少。
//	2、将原先采用单链表方式组织的字段结构改成hash链表方式,
//	查找字段基本上为常数级别O(1),速度有一定提高。
//
//	二、安全性方面的修改。
//	1、使用snprintf取代以前的sprintf。
//	2、使用xntoy系列函数保证缓冲区不越界。
//
//	三、移植性方面的修改。
//	1、将全部_???函数换成???函数。
//	2、将全部_???参数换成???参数。
//	3、针对Linux下面没有的几个函数在xntoy里面作了实现。
//
//	四、其它修改内容。
//	1、将函数位置进行了调整,相同功能部分放在了一起。
//	2、将函数名称进行了调整,基本上采用ODBC一致的名称。
//	3、将有副作用的Append函数和读字段值函数进行了调整。
//	4、对相关数据结构进行了调整。
//	5、对一次读写多条记录的函数及相关内容全部删除。
//*************************************************************

#define   LOCK_F_OFFSET		0x40000000L   // Foxpro Table without CDX Index file
#define   LOCK_C_OFFSET		1000000000L   // Code base use this
#define   LOCK_FILE_LEN		0x3FFFFFFFL

#define   LOCK_DBF_BEGIN    LOCK_C_OFFSET
#define   LOCK_DBF_LENGTH   (LOCK_FILE_LEN + (LOCK_F_OFFSET - LOCK_C_OFFSET) + 1)

#define   LOCK_CDX_TABLE_OFFSET 0x7FFFFFFE    // Foxpro Table with CDX Index file, decrement
#define   WAIT_TIME			1L

static void _dos_getdate ( struct _dosdate_t *ddate )
{
	time_t t;
	struct tm * ptm;

	time(&t);
	ptm = localtime(&t);
	ddate-> year  = ptm->tm_year+1990; //t. GetYear ();
	ddate-> month = ptm->tm_mon + 1;   //t. GetMonth ();
	ddate-> day   = ptm->tm_mday;      //t. GetDay ();
}

static long  GetDate( void )
{
    struct _dosdate_t ddate;
    _dos_getdate( &ddate );
    return ( ( ddate.year ) * 10000L + ddate.month * 100L + ddate.day ) ;
}

static long GetTime( void )
{
    struct tm * cur_time ;
    time_t long_time ;
    time( &long_time ) ;
    cur_time = localtime ( &long_time ) ;
    return (cur_time->tm_hour * 10000lu + 
			cur_time->tm_min * 100lu +
			cur_time->tm_sec ) ;
}


char * formatstr(char *str)
{
	char * tmp;
	char * tmp2;
	tmp = str;
	while (*tmp) tmp++;
	if(*str) tmp--;
	while (*tmp==' ') tmp--;
	*(tmp+1) = 0;
	tmp = str;
	tmp2 = str;
	while ( *tmp2 == ' ' ) tmp2 ++ ;
	while ( *tmp2 != 0 ) 
	{
		*tmp = *tmp2; tmp ++; tmp2 ++;
	}
	*tmp = 0;
	return str;
}

char * Trim(char *str)
{
	char *p;
	int   i,len;

	if((str==NULL) || (*str==0)) 
		return (char *)str;

	for(p=str, len=0; *p; p++) len++;
	for(p=str,i=len-1;(i>=0) && (p[i]==' ');i--) 
		len--;
	str[i+1] = 0;
	for(; (*p==' '); p++) len--;
	memmove(str,p,len+1);

	return (char *)str;
}

inline void Dbf::_SetDosDate(DBF_HEAD *phead)
{
    struct _dosdate_t datep ;
	if(phead)
	{
		_dos_getdate( &datep );
		phead->last_update[0] = (uchar)(datep.year % 100);
		phead->last_update[1] = (uchar)(datep.month);
		phead->last_update[2] = (uchar)(datep.day);
	}
}

/******************************************************************************/
uint shash(const char *s, int n)
{
	uint h;
	int  i;
	uchar *p;

	for (h=i=0,p=(uchar *)s; (i<n) && (*p); p++, i++)
		h = 31 * h + *p;

	return (h % MAX_FIELDS);
}

inline BOOL Dbf::insert_field_hashnode(FIELD_HASHNODE *pnode)
{
	int index;
	FIELD_HASHNODE *ptmp, *p;

	index = shash(dbf_handle->field_list[pnode->index]->field_rec.field_name, 11);
	ptmp = dbf_handle->field_hashnode[index];
	if(ptmp)
	{
		p = ptmp;
		while(p)
		{
			if(strnicmp(dbf_handle->field_list[pnode->index]->field_rec.field_name,
					   dbf_handle->field_list[p->index]->field_rec.field_name, 11)==0)
				return FALSE;
			p = p->next;
		}
		pnode->next = ptmp;
		dbf_handle->field_hashnode[index] = pnode;
	}
	else
	{
		dbf_handle->field_hashnode[index] = pnode;
		pnode->next = NULL;
	}
	return TRUE;
}

FIELD_LIST * Dbf::look_field(const char *field_name)
{
	char fname[12];
	int index;
	FIELD_HASHNODE *pnode;
	FIELD_LIST *plist;

	strncpy(fname, field_name, sizeof(fname));
	fname[sizeof(fname)-1] = 0;
	strupr(fname);
	index = shash(fname, sizeof(fname)); //field_name, strlen(field_name));
	pnode = dbf_handle->field_hashnode[index];
	if(pnode==NULL) return NULL;
	while(pnode)
	{
		plist = dbf_handle->field_list[pnode->index];
		if(strnicmp(plist->field_rec.field_name,field_name,11)==0)
			return plist;
		pnode = pnode->next;
	}
	return NULL;
}

/******************************************************************************/
Dbf::Dbf( void )
{
    dbf_handle	= NULL;
    lock		= 0;
    open_way	= RDWR;
}

Dbf::~Dbf()
{
	if( (dbf_handle != NULL ) && (dbf_handle->handle != -1) )
	{
		Close() ;
	}
}

int  Dbf::read_dbfhead( void )
{
	int start = 1;
    FIELD_REC field_rec;
	FIELD_HASHNODE *field_node;
    FIELD_LIST * flist_ptr;
	
    if ( (dbf_handle == NULL ) || (dbf_handle->handle==-1) )
		return -1 ;
	
    if( read( dbf_handle->handle, (char *)(&dbf_handle->dbf_head),sizeof(DBF_HEAD))!= sizeof(DBF_HEAD))
        return -1 ;

    dbf_handle->field_num = 0;
	for(;;)
    {
		//文件终止。
        if( read(dbf_handle->handle, (char *)&field_rec, sizeof(FIELD_REC)) != sizeof(FIELD_REC))
			break;

		if(field_rec.field_name[0] == 0x0d)	//字段结束
			break;

		flist_ptr  = new FIELD_LIST ;
		field_node = new FIELD_HASHNODE;
        if ((flist_ptr == NULL) || (field_node==NULL))
        {
            printf("Error allocate memory.\n");
			return -1;
        }
		flist_ptr->m_start = start;
		flist_ptr->cname   = NULL;
        memcpy( (char *)&flist_ptr->field_rec, (char *)&field_rec, sizeof(FIELD_REC));
		start += FieldLen(flist_ptr);
        dbf_handle->field_list[dbf_handle->field_num] = flist_ptr;
		field_node->index = dbf_handle->field_num;
		field_node->next  = NULL;
		if(insert_field_hashnode(field_node)==FALSE)
		{//存在重复的字段。
			delete field_node;
			delete flist_ptr;
			dbf_handle->field_list[dbf_handle->field_num] = NULL;
			continue;
		}
        dbf_handle->field_num ++;
		if(dbf_handle->field_num==MAX_FIELDS)
			break;
    }

    return 1;
}

BOOL Dbf::Open(const char * filename,char openway)
{
	int strLen1 ;

	if( dbf_handle != NULL)
		Close();

	dbf_handle = new DBF_HANDLE ;
	
	if ( !dbf_handle ) 
		return FALSE;

	memset(dbf_handle, 0, sizeof(DBF_HANDLE));

	dbf_handle->curr_rec	= 1L ;
	open_way = openway;

	if( open_way == RDONLY )
		dbf_handle->handle = open( filename, O_RDONLY | O_BINARY, S_IREAD );
//		dbf_handle->handle = _sopen( filename, _O_RDONLY | _O_BINARY, _SH_DENYNO, _S_IREAD );
	else
		dbf_handle->handle = open( filename, O_RDWR | O_BINARY, S_IREAD | S_IWRITE );
//		dbf_handle->handle = _sopen( filename, _O_RDWR | _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE );
		
	if (dbf_handle->handle == -1)
		goto error;

	if (read_dbfhead() == -1)
		goto error2;
	
	dbf_handle->record_buf = new char[dbf_handle->dbf_head.rec_size];
	if ( dbf_handle->record_buf == NULL )
		goto error2;

	strLen1 = strlen( filename );
	dbf_handle->file_name = new char [ strLen1 + 1 ];
	if(dbf_handle->file_name == NULL) 
		goto error2;
	strcpy(dbf_handle->file_name, filename);

	return TRUE;

error2:
	close(dbf_handle->handle);
error:
	delete dbf_handle;
	dbf_handle = NULL ;
	return FALSE ;
}

void Dbf::Close( void )
{
	FIELD_HASHNODE *pnode, *p;
	FIELD_LIST *plist;

	if( dbf_handle == NULL)
		return ;

	if(dbf_handle->handle != -1)
	{
		close(dbf_handle->handle);
		dbf_handle->handle = -1;
	}

	for(int i=0;i<MAX_FIELDS;i++)
	{
		plist = dbf_handle->field_list[i];
		if(plist)
		{
			if(plist->cname)
				delete plist->cname;
			delete plist;
		}
		
		pnode = dbf_handle->field_hashnode [i];
		while(pnode)
		{
			p = pnode;
			pnode = pnode->next;
			delete p;
		}
	}

	if(dbf_handle->record_buf)
		delete dbf_handle->record_buf;

	if(dbf_handle->file_name)
		delete dbf_handle->file_name;

	delete dbf_handle;
	dbf_handle = NULL ;
}

BOOL Dbf::Create(const char * file_name, FIELD_REC  * field)
{
	int fd, i;
	char ch[2];
	DBF_HEAD * phead = new DBF_HEAD;

	memset( phead, 0, sizeof( DBF_HEAD ));
	phead->dbf_id = 3;
	_SetDosDate(phead);
	phead->last_rec = 0L;
	phead->data_offset = 33;
	phead->rec_size = 1;
	for(i=0; (strlen( ( field +  i )->field_name) != 0) ; i++)
	{
		strupr( ( field + i )->field_name);
		if ( ( field + i )->field_type != 'N')
			phead->rec_size += (ushort)( field + i )->linfo.wlen;
		else
			phead->rec_size += (ushort)( field + i )->linfo.N.len;
		phead->data_offset += 32;
	}

	if ((fd = open(file_name, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE)) == -1)
	{
		delete phead ;
		return FALSE ;
	}
	write(fd, phead, 32);
	for(i=0; (strlen( ( field + i )->field_name) != 0); i++)
	{
		write(fd, (field + i ), sizeof( FIELD_REC ) );
	}
	ch[0] = 0x0d; ch[1] = 0x1a;
	write(fd, ch, 2);
	close(fd);
	delete phead;
	return ( Open( file_name ) );
}

BOOL Dbf::Zap( void )
{
	DBF_HEAD   * phead;
	FIELD_REC  * pfield;
	FIELD_LIST * plist;
	int  i, fd;
	char ch[2];

	if(dbf_handle == NULL || dbf_handle->handle == -1)
		return FALSE;

	phead = &(dbf_handle->dbf_head);
	_SetDosDate(phead);
	phead->last_rec = 0L;
	dbf_handle->curr_rec = 1L ;
	close(dbf_handle->handle);
	dbf_handle->handle = -1;

	if ((fd = open(dbf_handle->file_name, O_CREAT | O_TRUNC | O_RDWR, S_IREAD | S_IWRITE)) == -1)
	{// zap fail  
		return FALSE ;
	}
	write(fd, (char *)phead, 32);
	for(i=0;i<MAX_FIELDS;i++)
	{
		plist = dbf_handle->field_list[i];
		if(plist == NULL) break;
		pfield = &(plist->field_rec);
		write(fd, (char *)(pfield), 32);
	}
	ch[0] = 0x0d; ch[1] = 0x1a;
	write(fd, ch, 2);
	dbf_handle->handle = fd;
	return TRUE ;
}

//cursor move function(s)
BOOL Dbf::Move(long rec_num)
{
	size_t size;
	if( dbf_handle == NULL || dbf_handle->handle == -1)
		return ( FALSE ) ;

	if(rec_num > ReadRecordCount()) 
		rec_num = ReadRecordCount();

	if(rec_num < 1) 
		rec_num = 1;

	char * record_buf = dbf_handle->record_buf ;
	if(lock)
	{
		if ( lock_dbf_rec( rec_num, 1 ) != TRUE )
			return FALSE;
	}
	
	if ( lseek ( dbf_handle->handle, (long) dbf_handle->dbf_head.data_offset +
				 (long)(dbf_handle->dbf_head.rec_size) * ( rec_num -1 ), SEEK_SET) == -1)
		goto error;
	
	if ( ( size = read(dbf_handle->handle, record_buf,dbf_handle->dbf_head.rec_size) )
		     < (size_t)(dbf_handle->dbf_head.rec_size) )
		goto error;
	
	if(lock) unlock_dbf_rec(rec_num,1);
	dbf_handle->curr_rec = rec_num ;     
	return TRUE;
error:
	if(lock) unlock_dbf_rec( rec_num, 1); 
	return FALSE;
}

BOOL Dbf::MoveNext( long rec_num )
{
	if( dbf_handle == NULL || dbf_handle->handle == -1)
		return FALSE;

	return ( Move( dbf_handle->curr_rec + rec_num ) ) ;
}

BOOL Dbf::MoveFirst( void )
{
   return ( Move( 1l ) ) ;
}

BOOL Dbf::MoveLast( void )
{
   return (Move(ReadRecordCount())) ;
}

long Dbf::RecNo( void )
{
	if( dbf_handle == NULL || dbf_handle->handle == -1)
		return 0;

	return (GetRecordCount()<1) ? 0L : (dbf_handle->curr_rec) ;
}

long Dbf::GetRecordCount( void )
{
    if (dbf_handle ==NULL || dbf_handle->handle == -1 )
		return -1L;
    return dbf_handle->dbf_head.last_rec;
}

long Dbf::ReadRecordCount( void )
{
    if (dbf_handle == NULL || dbf_handle->handle == -1 )
        return -1L;
    lseek(dbf_handle->handle, 4L, SEEK_SET);
    read(dbf_handle->handle, &(dbf_handle->dbf_head.last_rec), 
		sizeof(dbf_handle->dbf_head.last_rec) );
    return  ( dbf_handle->dbf_head.last_rec ) ;
}

void Dbf::ClearRecBuf( void )
{
    if( dbf_handle == NULL || dbf_handle->handle == -1 )
		return ;
    char * record_buf =  dbf_handle->record_buf ;
    memset( record_buf , 0, dbf_handle->dbf_head.rec_size);
}

////
BOOL Dbf::Delete( long rec_num  )
{
    if( dbf_handle == NULL || dbf_handle->handle == -1 )
		return ( FALSE ) ;
	
    if( rec_num == 0L )	rec_num = dbf_handle->curr_rec ;
	
    if (rec_num < 1 || rec_num > dbf_handle->dbf_head.last_rec)
		return FALSE ;
	
    dbf_handle->record_buf[ 0 ] = '*';

	return _Update(rec_num, 1);
}

BOOL Dbf::IsDelete ( void )
{

⌨️ 快捷键说明

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