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

📄 recordfile.cpp

📁 一款不错的关于绘制波形编程的软件源代码
💻 CPP
字号:
#include "stdafx.h"
#include "RecordFile.h"

#define PAGE_LENGTH				528
#define PAGE_SIGNATURE			"LAUNCH"

#define OFFSET_SIGNATURE		0x00
#define OFFSET_INTERVAL			0x06
#define OFFSET_INDEXINBLOCK		0x07
#define OFFSET_BCDDATETIME		0x08
#define OFFSET_STATUS			0x0F
#define OFFSET_RESERVED			0x10
#define OFFSET_DATARECORD		0x14
#define OFFSET_GPSDATA			0x200

#define SIZE_DATARECORD			82
#define SIZE_GPSDATA			16

#define COUNT_DATARECORD		6

#define TIMEOFFSET_SECOND		0x00
#define TIMEOFFSET_MINUTE		0x01
#define TIMEOFFSET_HOUR			0x02
#define TIMEOFFSET_WEEK			0x03
#define TIMEOFFSET_DAY			0x04
#define TIMEOFFSET_MONTH		0x05
#define TIMEOFFSET_YEAR			0x06


IMPLEMENT_DYNAMIC(CRecordException, CException)

CRecordException::CRecordException(int cause, DWORD osError, LPCTSTR fileName)
{
	m_cause = cause;
	m_osError = osError;
	m_fileName = fileName;
}

CRecordException::~CRecordException()
{
}

void CRecordHelper::GetDateTime(COleDateTime& dt, const BYTE* pBcddt)
{
	dt.SetDateTime(2000+pBcddt[TIMEOFFSET_YEAR]/16*10 + pBcddt[TIMEOFFSET_YEAR]%16,\
		pBcddt[TIMEOFFSET_MONTH]/16*10 + pBcddt[TIMEOFFSET_MONTH]%16, \
		pBcddt[TIMEOFFSET_DAY]/16*10 + pBcddt[TIMEOFFSET_DAY]%16,
		pBcddt[TIMEOFFSET_HOUR]/16*10 + pBcddt[TIMEOFFSET_HOUR]%16,\
		pBcddt[TIMEOFFSET_MINUTE]/16*10 + pBcddt[TIMEOFFSET_MINUTE]%16,\
		pBcddt[TIMEOFFSET_SECOND]/16*10 + pBcddt[TIMEOFFSET_SECOND]%16);

}
CRecordFile::CRecordFile()
{	
	m_pageCount = 0	;
}


CRecordFile::CRecordFile(LPCTSTR filePath)
{
	m_fileSize = MapRecordFile(filePath);
	m_filePath = filePath;
	
	m_pageCount = m_fileSize / PAGE_LENGTH;
	m_startPageIndex = 0;
	m_endPageIndex = m_pageCount - 1;
	m_startRecordIndex = 0;
	m_endRecordIndex = COUNT_DATARECORD - 1;
}

CRecordFile::CRecordFile(LPCTSTR filePath, const COleDateTime& startTime)
{
	m_fileSize = MapRecordFile(filePath);
	m_filePath = filePath;
	
	m_pageCount = m_fileSize / PAGE_LENGTH;
	m_startPageIndex = 0;
	m_endPageIndex = m_pageCount - 1;
	m_startRecordIndex = 0;
	m_endRecordIndex = COUNT_DATARECORD - 1;

	CDataPage page;
	COleDateTime dtPage;
	COleDateTimeSpan dtSpanOfPage;

	GetDataPageAt(0, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);

	if (dtPage >= startTime)
	{
		m_startPageIndex = 0;
		m_endPageIndex = m_pageCount - 1;
		m_startRecordIndex = 0;
		m_endRecordIndex = COUNT_DATARECORD - 1;
		return;
	}

	GetDataPageAt(m_pageCount-1, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
	if (dtPage + dtSpanOfPage < startTime)
	{
		throw new CRecordException(CRecordException::timeOutOfRange, 0, m_filePath);
	}

	UINT recordIndex;
	FindDataPageAfter(startTime, &page, &recordIndex);

	m_startPageIndex = page.pageIndex;
	m_endPageIndex = m_pageCount - 1;
	m_startRecordIndex = recordIndex;
	m_endRecordIndex = COUNT_DATARECORD - 1;
}

CRecordFile::CRecordFile(LPCTSTR filePath, const COleDateTime& startTime, const COleDateTime& endTime)
{
	if (startTime > endTime)
	{
		throw new CRecordException(CRecordException::invalidParameter, 0, m_filePath);
	}

	m_fileSize = MapRecordFile(filePath);
	m_filePath = filePath;
	
	m_pageCount = m_fileSize / PAGE_LENGTH;
	m_startPageIndex = 0;
	m_endPageIndex = m_pageCount - 1;
	m_startRecordIndex = 0;
	m_endRecordIndex = COUNT_DATARECORD - 1;
	
	CDataPage page;
	COleDateTime dtPage;
	COleDateTimeSpan dtSpanOfPage;
	
	GetDataPageAt(0, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	if (dtPage > endTime)
	{
		throw new CRecordException(CRecordException::timeOutOfRange, 0, m_filePath);
	}

	GetDataPageAt(m_pageCount-1, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
	if (dtPage + dtSpanOfPage < startTime)
	{
		throw new CRecordException(CRecordException::timeOutOfRange, 0, m_filePath);
	}

	CDataPage startPage, endPage;
	UINT startRecordIndex, endRecordIndex;
	FindDataPageAfter(startTime, &startPage, &startRecordIndex);
	m_startPageIndex = startPage.pageIndex;
	m_startRecordIndex = startRecordIndex;

	FindDataPageBefore(endTime, &endPage, &endRecordIndex);
	m_endPageIndex = endPage.pageIndex;	
	m_endRecordIndex = endRecordIndex;
}

CRecordFile::~CRecordFile()
{
	UnmapRecordFile();
}

long CRecordFile::GetDataPageCount() const
{
	return m_pageCount;
}


void CRecordFile::GetHeadDataPage(CDataPage* pOutPage)
{	
	GetDataPageAt(m_startPageIndex, pOutPage);
}

void CRecordFile::GetTailDataPage(CDataPage* pOutPage)
{
	GetDataPageAt(m_endPageIndex, pOutPage);
}

void CRecordFile::GetDataPageAt(UINT index, CDataPage* pOutPage)
{
	pOutPage->Clear();

	if (index > m_endPageIndex)
	{
		return;
	}

	UINT pageOffset = index * PAGE_LENGTH;
	
	if (memcmp(m_pvFile+pageOffset+OFFSET_SIGNATURE, 
		PAGE_SIGNATURE, strlen(PAGE_SIGNATURE)))
	{
		throw new CRecordException(CRecordException::invalidFormat, 0, m_filePath);
	}		

	pOutPage->pageAddr = m_pvFile + pageOffset;		
	pOutPage->pageIndex = index;
	pOutPage->pageSize = PAGE_LENGTH;
	pOutPage->dataCount = COUNT_DATARECORD;		
	pOutPage->dataSize = SIZE_DATARECORD;		
	pOutPage->dataOffset = OFFSET_DATARECORD;	
	pOutPage->gpsOffset = OFFSET_GPSDATA;	
	pOutPage->bcdTimeOffset = OFFSET_BCDDATETIME;
	int interval = m_pvFile[pageOffset + OFFSET_INTERVAL];
	pOutPage->interval = (interval == 0) ? 1 : interval;		
	pOutPage->indexInBlock = m_pvFile[pageOffset + OFFSET_INDEXINBLOCK];
	pOutPage->status = m_pvFile[pageOffset + OFFSET_STATUS];
	pOutPage->isValid = TRUE;	
}

void CRecordFile::FindDataPageAfter(const COleDateTime& time, CDataPage* pOutPage, UINT* recordIndex)
{
	UINT startIndex = m_startPageIndex;
	UINT endIndex = m_endPageIndex;

	int i;
	CDataPage page;
	COleDateTime dtPage;
	COleDateTimeSpan dtSpanOfPage;

	GetDataPageAt(endIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
	if (dtPage + dtSpanOfPage < time)
	{
		// no data available
		pOutPage->Clear();
		*recordIndex = -1;
		return;
	}
	
	GetDataPageAt(startIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);

	for (i=0; i<COUNT_DATARECORD; ++i)
	{
		dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
		if (dtPage + dtSpanOfPage >= time)
		{
			// found data
			GetDataPageAt(startIndex, pOutPage);
			*recordIndex = i;
			return;
		}
	}
	
	UINT middleIndex;
	while (startIndex <= endIndex)
	{
		middleIndex = (startIndex + endIndex) / 2;

		GetDataPageAt(middleIndex, &page);
		CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);

		if (dtPage > time)
		{
			endIndex = middleIndex - 1;
			continue;
		}

		else if(dtPage<=time)
		{
			dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
			if (dtPage + dtSpanOfPage >= time)
			{
				for (i=0; i<COUNT_DATARECORD; ++i)
				{
					dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
					if (dtPage + dtSpanOfPage >= time)
					{
						// found data
						GetDataPageAt(middleIndex, pOutPage);
						*recordIndex = i;
						return;
					}
				}	
			}
			else
			{
				startIndex = middleIndex + 1;
				continue;
			}
		}

// 		for (i=0; i<COUNT_DATARECORD; ++i)
// 		{
// 			dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
// 			if (dtPage + dtSpanOfPage >= time)
// 			{
// 				// found data
// 				GetDataPageAt(startIndex, pOutPage);
// 				*recordIndex = i;
// 				return;
// 			}
// 		}
	}
	if(startIndex == endIndex)
	{
		pOutPage->Clear();
		*recordIndex = -1;
		return;
	}
}

void CRecordFile::FindDataPageBefore(const COleDateTime& time, CDataPage* pOutPage, UINT* recordIndex)
{
	UINT startIndex = m_startPageIndex;
	UINT endIndex = m_endPageIndex;
	
	int i;
	CDataPage page;
	COleDateTime dtPage;
	COleDateTimeSpan dtSpanOfPage;
	
	GetDataPageAt(endIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
	if (dtPage + dtSpanOfPage <=time)
	{
		// no data available
		GetDataPageAt(endIndex, pOutPage);
		*recordIndex = COUNT_DATARECORD - 1;
		return;
	}
	
	GetDataPageAt(startIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	
	for (i=0; i<COUNT_DATARECORD; ++i)
	{
		dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
		if (dtPage + dtSpanOfPage >= time)
		{
			// found data
			GetDataPageAt(startIndex, pOutPage);
			*recordIndex = i;
			return;
		}
	}
	
	UINT middleIndex;
	while (startIndex <= endIndex)
	{
		middleIndex = (startIndex + endIndex) / 2;
		
		GetDataPageAt(middleIndex, &page);
		CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
		
		if (dtPage > time)
		{
			endIndex = middleIndex - 1;
			continue;
		}
		
		else if(dtPage<=time)
		{
			dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
			if (dtPage + dtSpanOfPage >= time)
			{
				for (i=0; i<COUNT_DATARECORD; ++i)
				{
					dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
					if (dtPage + dtSpanOfPage >= time)
					{
						// found data
						GetDataPageAt(middleIndex, pOutPage);
						*recordIndex = i;
						return;
					}
				}	
			}
			else
			{
				startIndex = middleIndex + 1;
				continue;
			}
		}
		
	}
	if(startIndex == endIndex)
	{
		pOutPage->Clear();
		*recordIndex = -1;
		return;
	}
}

void CRecordFile::GetDataPageAt(COleDateTime time, CDataPage* pOutPage)
{
	UINT startIndex = m_startPageIndex;
	UINT endIndex = m_endPageIndex;
	
	int i;
	CDataPage page;
	COleDateTime dtPage;
	COleDateTimeSpan dtSpanOfPage;
	
	GetDataPageAt(endIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
	if (dtPage + dtSpanOfPage < time)
	{
		// no data available
		pOutPage->Clear();
		return;
	}

	GetDataPageAt(startIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	if (dtPage > time)
	{
		// no data available
		pOutPage->Clear();
		return;
	}
	
	GetDataPageAt(startIndex, &page);
	CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
	
	for (i=0; i<COUNT_DATARECORD; ++i)
	{
		dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
		if (dtPage + dtSpanOfPage >= time)
		{
			// found data
			GetDataPageAt(startIndex, pOutPage);
			return;
		}
	}
	
	UINT middleIndex;
	while (startIndex <=endIndex)
	{
		middleIndex = (startIndex + endIndex) / 2;
		
		GetDataPageAt(middleIndex, &page);
		CRecordHelper::GetDateTime(dtPage, page.pageAddr+page.bcdTimeOffset);
		
		if (dtPage > time)
		{
			endIndex = middleIndex - 1;
			continue;
		}	
		else if(dtPage<=time)
		{
			dtSpanOfPage.SetDateTimeSpan(0, 0, 0, COUNT_DATARECORD*page.interval);
			if (dtPage + dtSpanOfPage >= time)
			{
				for (i=0; i<COUNT_DATARECORD; ++i)
				{
					dtSpanOfPage.SetDateTimeSpan(0, 0, 0, i*page.interval);
					if (dtPage + dtSpanOfPage >= time)
					{
						// found data
						GetDataPageAt(middleIndex, pOutPage);
						return;
					}
				}	
			}
			else
			{
				startIndex = middleIndex + 1;
				continue;
			}
		}
		
	}
	if(startIndex == endIndex)
	{
		pOutPage->Clear();
		return;
	}
}


void CRecordFile::GetNextDataPage(CDataPage* pCurPage, CDataPage* pOutPage)
{
	pOutPage->Clear();
	if (pCurPage->pageIndex < m_endPageIndex)
	{
		GetDataPageAt(pCurPage->pageIndex+1, pOutPage);
	}
}

void CRecordFile::GetPrevDataPage(CDataPage* pCurPage, CDataPage* pOutPage)
{
	pOutPage->Clear();
	
	if (pCurPage->pageIndex > m_startPageIndex)
	{
		GetDataPageAt(pCurPage->pageIndex-1, pOutPage);
	}
}

void CRecordFile::GetDataPageRelativeTo(CDataPage* pCurPage, int offset, CDataPage* pOutPage)
{
	pOutPage->Clear();
	
	if (pCurPage->pageIndex != m_startPageIndex
		&& pCurPage->pageIndex != m_endPageIndex)
	{
		UINT newPageIndex;
		if (pCurPage->pageIndex + offset < m_startPageIndex)
		{
			newPageIndex = m_startPageIndex;
		}
		else if (pCurPage->pageIndex + offset > m_endPageIndex)
		{
			newPageIndex = m_endPageIndex;
		}
		else
		{
			newPageIndex = pCurPage->pageIndex + offset;
		}
		
		GetDataPageAt(newPageIndex, pOutPage);
	}
}

void CRecordFile::GetDataPageMiddleOf(UINT start, UINT end, CDataPage* pOutPage)
{
	pOutPage->Clear();

	if (start <= end && start >= m_startPageIndex
		&& end <= m_endPageIndex)
	{
		UINT middle = (start + end) / 2;
		GetDataPageAt(middle, pOutPage);
	}
}

void CRecordFile::GetHeadDataPageTime(COleDateTime& dt)
{
	CDataPage page;
	GetDataPageAt(m_startPageIndex, &page);
	CRecordHelper::GetDateTime(dt, page.pageAddr+page.bcdTimeOffset);
}

void CRecordFile::GetTailDataPageTime(COleDateTime& dt)
{
	CDataPage page;
	GetDataPageAt(m_endPageIndex, &page);
	CRecordHelper::GetDateTime(dt, page.pageAddr+page.bcdTimeOffset);
}

DWORD CRecordFile::MapRecordFile(LPCTSTR filePath)
{
	DWORD fileSize = 0;
	
	m_hFile = CreateFile(filePath, GENERIC_READ, 0, 
		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	
	if (m_hFile == INVALID_HANDLE_VALUE) 
	{ 
		throw new CRecordException(CRecordException::fileOpenFailed, GetLastError(), filePath);
	} 
	
	fileSize = GetFileSize(m_hFile, NULL); 
	if (fileSize == 0xFFFFFFFF)
	{
		DWORD lastError = GetLastError();
		CloseHandle(m_hFile); 
		throw new CRecordException(CRecordException::fileOpenFailed, lastError, filePath);
	}

	if (!fileSize || fileSize % PAGE_LENGTH != 0)
	{
		CloseHandle(m_hFile); 
		throw new CRecordException(CRecordException::invalidFileLength, 0, filePath);
	}

	m_hFileMapping = CreateFileMapping(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL); 
	if (m_hFileMapping == NULL)
	{ 
		DWORD lastError = GetLastError();
		CloseHandle(m_hFile); 
		throw new CRecordException(CRecordException::fileOpenFailed, lastError, filePath);
	} 
	
	m_pvFile = (BYTE *)MapViewOfFile(m_hFileMapping, FILE_MAP_READ, 0, 0, 0); 
	if (m_pvFile == NULL)
	{ 
		DWORD lastError = GetLastError();
		CloseHandle(m_hFileMapping); 
		CloseHandle(m_hFile); 
		throw new CRecordException(CRecordException::fileOpenFailed, lastError, filePath);
	} 
	
	if (memcmp(m_pvFile, PAGE_SIGNATURE, strlen(PAGE_SIGNATURE)) 
		|| memcmp(m_pvFile+fileSize-PAGE_LENGTH, PAGE_SIGNATURE, strlen(PAGE_SIGNATURE)))
	{
		DWORD lastError = GetLastError();
		UnmapViewOfFile(m_pvFile);
		CloseHandle(m_hFileMapping); 
		CloseHandle(m_hFile); 
		throw new CRecordException(CRecordException::invalidFormat, lastError, filePath);
	}

	return fileSize;
}

void CRecordFile::UnmapRecordFile()
{
	if (m_pvFile)
	{
		UnmapViewOfFile(m_pvFile); 
		m_pvFile = NULL;
	}
	if (m_hFileMapping)
	{
		CloseHandle(m_hFileMapping); 	
		m_hFileMapping = NULL;
	}
	if (m_hFile)
	{
		CloseHandle(m_hFile); 
		m_hFile = NULL;
	}
}

⌨️ 快捷键说明

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