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

📄 mydbf.cpp

📁 DBF文件解析读取 普通字段类型解析 其他
💻 CPP
字号:


#include "stdafx.h"
#include "MyDBF.h"


#include <iostream>



CMyDBF::CMyDBF()
{

}

CMyDBF::~CMyDBF()
{

}

void CMyDBF::SetDBFFile(std::string &FilePath)
{
	m_strDBFFile = FilePath;
}

// 设置 内存池大小 及 增减值
// 数据读取完成之后 可用空间 小于 StepNum 申请 StepNum 空间
//					可用空间 大于 StepNum 释放 (StepNum / 2)空间
void CMyDBF::SetPoolParms(int InitNum, int StepNum)
{
	m_szPoolInitNum = InitNum;
	m_szPoolStepNum = StepNum;
}

// 读取 dbf 头部 字段参数
// 内存池 申请 足够的空间
bool CMyDBF::Init()
{
	std::fstream fs;
	fs.open(m_strDBFFile.c_str(),std::ios::in | std::ios::binary);

	if (! fs.good())
		return false;

	// 读取头部 
	// 读取前面 32 字节
	unsigned char Data[36];
	unsigned char c;
	
	fs.seekg(0);
	
	int i = 0;
	memset(Data,0,sizeof(Data));
	while(i < 32)
	{
		c = fs.get();	

		if (fs.eof())
		{
			fs.close();
			
			return false;
		}
		
		Data[i++] = c;
	}
	
	long * pRecordNum = (long*)(Data + 4);
	m_szHeader.RecordsNum = *pRecordNum;
	
	short * pHeaderSize = (short *)(Data + 8);
	m_szHeader.HeaderSize = *pHeaderSize;
	
	short * pRecordSize = (short *)(Data + 10);
	m_szHeader.RecordSize = *pRecordSize;
	
	
	//字段数据
	m_szFieldsVec.clear();

	// 最后一个字符 0x0D 不读取
	int Size = m_szHeader.HeaderSize - 32 - 1;
	
	// 最多 100 字段  100 * 32 字节 = 3200
	char Buff[1024*4];
	memset(Buff,0,sizeof(Buff));
	
	fs.seekg(32);
	
	i = 0;
	
	while(i < Size)
	{
		c = fs.get();
		
		if (fs.eof())
		{
			fs.close();
			
			return false;
		}
		
		Buff[i] = c;
		
		i++;
	}

	// 关闭文件
	fs.close();
	
	// 所有的头部分数据读完
	i = 0;
	int Offsize = 1;
	
	while(i < Size)
	{
		// 分析字段
		memset(Data,0,sizeof(Data));
		
		int j = 0;
		while(j < 32)
		{
			Data[j++] = Buff[i++];//*((unsigned char*)pData + (i++));
		}
		
		_FIELD szField;
		memset(&szField,0,sizeof(_FIELD));
		
		strcpy(szField.Name,(char*)Data);
		_strupr(szField.Name);
		
		long *pOffsize = (long*)(Data + 12);
		
		if (*pOffsize == 0)
			szField.RecordOffsize = Offsize;
		else
			szField.RecordOffsize = *pOffsize;
		
		szField.Len = (short)Data[16];
		
		Offsize += szField.Len;
		
		m_szFieldsVec.push_back(szField);
	}
	
	// 内存池
	m_szFreeVec.clear();

	for(i = 0; i < m_szPoolInitNum; i++)
	{
		void *pRecord = malloc(m_szHeader.RecordSize);

		if (pRecord == NULL)
		{
			// 内存不足 直接返回
			return false;
		}

		m_szFreeVec.push_back(pRecord);
	}

	return true;
}

// 释放内存池
void CMyDBF::Uninit()
{
	int i;
	
	// 释放已经使用的空间
	for(i = 0; i < m_szRecordVec.size(); i++)
	{
		void *pRecord = m_szRecordVec.at(i);
		
		free(pRecord);
		
		m_szRecordVec.at(i) = NULL;
	}
	
	// 释放未被使用的空间
	for(i = 0; i < m_szFreeVec.size(); i++)
	{
		void *pRecord = m_szFreeVec.at(i);
		
		free(pRecord);

		m_szFreeVec.at(i) = NULL;
	}
}

// 读取记录集数据
bool CMyDBF::ReadRecordsets()
{
	// 读取文件大小 
	std::fstream fs;
	fs.open(m_strDBFFile.c_str(),std::ios::in | std::ios::binary);

	if (! fs.good())
		return false;

	unsigned char c;
	int i;
	
	fs.seekg(m_szHeader.HeaderSize);
	
	bool bInvalid = false;
	
	// 读取所有记录
	while(! fs.eof())
	{
		void *pRecord = NULL;

		if (! GetPoolSpaceItem(&pRecord))
			break;
		
		i = 0;
		
		while(i < m_szHeader.RecordSize)
		{
			c = fs.get();
			
			if (fs.eof())
			{
				bInvalid = true;
				break;
			}

			*((unsigned char*)pRecord + i) = c;
			
			i++;
		}
		
		if (! bInvalid)
		{
			m_szRecordVec.push_back(pRecord);
		}
		else
		{
			// 放回去
			m_szFreeVec.push_back(pRecord);

			break;
		}
	}

	fs.close();

	// 查看是否释放空间
	if(m_szFreeVec.size() > m_szPoolStepNum)
	{
		int FreeNum = m_szFreeVec.size() - m_szPoolStepNum;

		for(i = 0; i < FreeNum; i++)
		{
			void *pRecord = m_szFreeVec.at(m_szFreeVec.size() - 1);
			
			m_szFreeVec.erase(m_szFreeVec.end() - 1);

			free(pRecord);
		}
	}
	
	return true;
}

// 释放记录集数据
void CMyDBF::ReleaseRecordsets()
{
	int i;
	
	// 将使用过的空间 放入未用列表
	for(i = 0; i < m_szRecordVec.size(); i++)
	{
		void *pRecord = m_szRecordVec.at(i);
		
		if (pRecord != NULL)
			m_szFreeVec.push_back(pRecord);
				
		m_szRecordVec.at(i) = NULL;
	}

	m_szRecordVec.clear();
}

bool CMyDBF::GetPoolSpaceItem(void **pSpaceItem)
{
	if (m_szFreeVec.empty())
		return false;

	*pSpaceItem = m_szFreeVec.at(m_szFreeVec.size() - 1);

	m_szFreeVec.erase(m_szFreeVec.end() - 1);

	// 查看是否要增加空间
	if (m_szFreeVec.size() < m_szPoolStepNum)
	{
		for(int i = 0; i < m_szPoolStepNum; i++)
		{
			void *pRecord = malloc(m_szHeader.RecordSize);
			
			if (pRecord == NULL)
			{
				// 内存不足 
				break;
			}
			
			m_szFreeVec.push_back(pRecord);
		}
	}

	return true;
}





// 获取某条记录某个字段的值
bool CMyDBF::GetFieldValue(void* pRecord, char *pFieldName, char* pData)
{
	char Data[64];

	memset(Data,0,sizeof(Data));
	strcpy(Data,pFieldName);

	_strupr(Data);

	std::string strName = Data;

	int FieldIndex = -1;

	for(int i = 0; i < m_szFieldsVec.size(); i++)
	{
		if (strName == m_szFieldsVec.at(i).Name)
		{
			FieldIndex = i;
			break;
		}
	}

	if (FieldIndex < 0)
		return false;

	memcpy(pData,((unsigned char*)pRecord + m_szFieldsVec.at(FieldIndex).RecordOffsize),
		m_szFieldsVec.at(FieldIndex).Len);

	return true;
}


void CMyDBF::GetDataChar(char* pData, std::string &strData)
{
	char Data[512];
	
	memset(Data,0,sizeof(Data));
	strcpy(Data,pData);

	strData = Data;

	BWSMGFun::TrimString(strData);
}

void CMyDBF::GetDataInteger(char* pData, long &szData)
{
	szData = *(long*)pData;
}

void CMyDBF::GetDataNumber(char* pData, double &dbData)
{
	char Data[64];
	
	memset(Data,0,sizeof(Data));
	strcpy(Data,pData);
	
	dbData = atof(Data);
}

// theTm 只存储数据 不做 tm 格式处理
void CMyDBF::GetDataDate(char* pData, tm &theTm)
{
	// 20070702
	char Data[64];
	
	memset(Data,0,sizeof(Data));
	memcpy(Data,pData,8);

	memset(&theTm,0,sizeof(tm));

	std::string strData = Data;

	theTm.tm_year = atol(strData.substr(0,4).c_str());
	theTm.tm_mon = atol(strData.substr(4,2).c_str());
	theTm.tm_mday = atol(strData.substr(6,2).c_str());
}

void CMyDBF::GetDataDatetime(char* pData, tm &theTm)
{
	char Data[64];
	
	memset(Data,0,sizeof(Data));
	memcpy(Data,pData,8);
	
	memset(&theTm,0,sizeof(tm));
	
	long DayNum = *(long*)Data;
	long MillionSeconds = *(long*)(Data + 4);

	/*
	The datevalue is stored as a day number since -4831 (or something like 
	that). A real date like 1 jan 1900 is daynumber 0x24d9ad and therefore 
	stored as ad d9 24 00 
	
	  Time is stored in number of milliseconds since 12 o'clock so 23.59.59 
	  will be 0x05265818 and therefore stored as 18 58 26 05 
	  Sometimes the entered time from the user will be slightly different 
	  from was is stored. e.g. the user enters 0:0:1 and it is stored as 999 
	  msec instead of 1000. So be sure to round the values instead of 
	  trunicating. 
	*/
	
	// 0001-01-01 0x001a4452
	// 
	theTm.tm_year = 1;
	theTm.tm_mon = 1;
	theTm.tm_mday = 1;
	theTm.tm_hour = 0;
	theTm.tm_min = 0;
	theTm.tm_sec = 0;
	
	int AddDays = DayNum - 0x001a4452;
	
	if (AddDays < 0)
		return ;
	
	int TheYear = 1;
	int TheMonth = 1;
	
	while(AddDays > 0)
	{
		int Day1 = BWSMGFun::GetDaysOfYears(TheYear);
		
		if (AddDays >= Day1)
		{
			// 增加 1 年
			theTm.tm_year += 1;
			
			TheYear ++;
			
			AddDays -= Day1;
		}
		else
		{
			// 增加一个月
			int Day1 = BWSMGFun::GetDaysOfMonth(TheYear,TheMonth);
			
			if (AddDays >= Day1)
			{
				theTm.tm_mon += 1;
				
				TheMonth++;
				
				AddDays -= Day1;
			}
			else
			{
				// 直接更改天数
				theTm.tm_mday += AddDays;
				
				AddDays = 0;
			}
		}
	}
	
	int AddSeconds = MillionSeconds / 1000 + (MillionSeconds % 1000 > 500 ? 1 : 0);
	
	while(AddSeconds > 0)
	{
		if (AddSeconds >= 3600)
		{
			theTm.tm_hour += 1;
			
			AddSeconds -= 3600;
		}
		else if (AddSeconds >= 60)
		{
			theTm.tm_min += 1;
			
			AddSeconds -= 60;
		}
		else 
		{
			theTm.tm_sec += AddSeconds;
			
			AddSeconds = 0;
		}
	}
}

//int CMyDBF::GetDaysOfYears(int Year)
//{
//	if ((Year % 4 == 0) && ((Year % 100 != 0) || (Year % 400 == 0)))
//		return 366;
//	else 
//		return 365;
//}
//
//int CMyDBF::GetDaysOfMonth(int Year, int Month)
//{
//	switch(Month) {
//	case 1:
//		return 31;
//	case 2:
//		if ((Year % 4 == 0) && ((Year % 100 != 0) || (Year % 400 == 0)))
//			return 29;
//		else 
//			return 28;
//	case 3:
//		return 31;
//	case 4:
//		return 30;
//	case 5:
//		return 31;
//	case 6:
//		return 30;
//	case 7:
//		return 31;
//	case 8:
//		return 31;
//	case 9:
//		return 30;
//	case 10:
//		return 31;
//	case 11:
//		return 30;
//	case 12:
//		return 31;
//	default:
//		return 0;
//	}
// }
//	

⌨️ 快捷键说明

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