📄 recordfile.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 + -