头文件TeaBinLog.h
/********************************************************************
purpose: 写二进制形式的日志文件,不支持多线程操作
*********************************************************************/
#pragma once
const UINT32 MAX_LOG_LEN = 1024;//单条日志的最大长度不能超过这个值,否则读/写都会失败
enum E_TEABINLOG_ERR
{
E_TEABINLOG_ERR_SUCCESS,//成功
E_TEABINLOG_ERR_OUTOF_RANGE,//日志长度过长
E_TEABINLOG_ERR_ACCESS_FAIL,//文件无法访问
E_TEABINLOG_ERR_READ_FAIL,//读取单条日志的过程中发生异常
};
//读取时的回调函数
//返回非0表示停止读取数据
typedef int (__stdcall *ReadCallFunction)(const UINT32 uLogId, BYTE *pBuf, UINT32 uBufLen);
class TeaBinLog
{
public:
TeaBinLog(void);
~TeaBinLog(void);
void SetFileName(TCHAR* lpszFileName);
int WriteLog(const UINT32 uLogId, const BYTE* const pBuf, const UINT32 uBufLen, UINT8 bEncrypt = 0);
int ReadLog(ReadCallFunction fn);
/*************************************************************************
Author : HuangYongbo [2013-10-23 15:29]
Function: 加密/解密,加密或者解密之后,缓冲区的长度应该保持不变
Parameters:
Return Value: If success return 0, otherwise return nonzero.
*************************************************************************/
virtual int Encrypt(const BYTE* const pBuf, const UINT32 uBufLen,
BYTE *pBufRet, BOOL bEncrypt);
private:
CFile m_file;
TCHAR m_szFileName[MAX_PATH];
bool m_bReadLoop;
};
源文件TeaBinLog.cpp
#include "StdAfx.h"
#include "TeaBinLog.h"
TeaBinLog::TeaBinLog(void):
m_bReadLoop(false)
{
ZeroMemory(m_szFileName, MAX_PATH);
}
TeaBinLog::~TeaBinLog(void)
{
}
int TeaBinLog::WriteLog( const UINT32 uLogId, const BYTE* const pBuf, const UINT32 uBufLen , UINT8 bEncrypt/* = 0*/)
{
if (uBufLen > MAX_LOG_LEN)
{
return E_TEABINLOG_ERR_OUTOF_RANGE;
}
if (FALSE == m_file.Open(m_szFileName, CFile::modeCreate|CFile::modeWrite|CFile::modeNoTruncate))
{
AfxMessageBox("打开文件失败。");
return E_TEABINLOG_ERR_ACCESS_FAIL;
}
int iFileLength = (int)m_file.GetLength();
m_file.SeekToEnd();
m_file.Write(&bEncrypt, sizeof(bEncrypt));
m_file.Write(&uLogId, sizeof(uLogId));
m_file.Write(&uBufLen, sizeof(uBufLen));
if ( 1 == bEncrypt)
{
//加密
BYTE *pTempBuf = new BYTE[uBufLen];
Encrypt(pBuf,uBufLen, pTempBuf, TRUE);
m_file.Write(pTempBuf, uBufLen);
delete []pTempBuf;
}
else
{
m_file.Write(pBuf, uBufLen);
}
m_file.Close();
return 0;
}
int TeaBinLog::ReadLog( ReadCallFunction fn )
{
if (FALSE == m_file.Open(m_szFileName, CFile::modeRead))
{
AfxMessageBox("打开文件失败。");
return E_TEABINLOG_ERR_ACCESS_FAIL;
}
m_file.SeekToBegin();
int nRet(0);
UINT32 uLogId(0);
UINT32 uLogLen(0);
UINT32 uReadRet(0);
UINT8 bEncrypt(0);
BYTE pBuf[MAX_LOG_LEN] = {};
m_bReadLoop = true;
while (m_bReadLoop)
{
//encrypt information
uReadRet = m_file.Read(&bEncrypt, sizeof(bEncrypt));
if (uReadRet < sizeof(bEncrypt))
{
nRet = E_TEABINLOG_ERR_READ_FAIL;
break;
}
//log id
uReadRet = m_file.Read(&uLogId, sizeof(uLogId));
if (uReadRet < sizeof(uLogId))
{
nRet = E_TEABINLOG_ERR_READ_FAIL;
break;
}
//log length
uReadRet = m_file.Read(&uLogLen, sizeof(uLogLen));
if (uReadRet < sizeof(uLogLen))
{
nRet = E_TEABINLOG_ERR_READ_FAIL;
break;
}
//log information
uReadRet = m_file.Read(pBuf, uLogLen);
if (uReadRet < uLogLen)
{
nRet = E_TEABINLOG_ERR_READ_FAIL;
break;
}
if ( 1 == bEncrypt)
{
//解密
BYTE *pTempBuf = new BYTE[uLogLen];
Encrypt(pBuf,uLogLen, pTempBuf, FALSE);
if(0 != fn(uLogId, pTempBuf, uLogLen))
{
m_bReadLoop = false;
}
delete []pTempBuf;
}
else
{
if (0 != fn(uLogId, pBuf, uLogLen))
{
m_bReadLoop =false;
}
}
}
m_file.Close();
return nRet;
}
void TeaBinLog::SetFileName( TCHAR* lpszFileName )
{
_tcscpy_s(m_szFileName, MAX_PATH*sizeof(TCHAR), lpszFileName);
}
int TeaBinLog::Encrypt( const BYTE* const pBuf, const UINT32 uBufLen,
BYTE *pBufRet,BOOL bEncrypt)
{
if (TRUE == bEncrypt)
{
//加密
for (UINT32 i=0; i<uBufLen; i++)
{
if (0xff == pBuf[i])
{
pBufRet[i] = 0;
}
else
{
pBufRet[i] = pBuf[i] + 1;
}
}
//memcpy(pBufRet, pBuf, uBufLen);
}
else
{
//解密
for (UINT32 i=0; i<uBufLen; i++)
{
if (pBuf[i] == 0)
{
pBufRet[i] = 0xff;
}
else
{
pBufRet[i] = pBuf[i] - 1;
}
}
//memcpy(pBufRet, pBuf, uBufLen);
}
return 0;
}
测试文件
#include "StdAfx.h"
#include "MainLog.h"
#include "TeaBinLog.h"
TeaBinLog g_log;
const UINT32 LOG_HEADER_LEN = 64;//日志头中,留100个字节去存储信息
struct LOG_HEADER
{
UINT32 uVer;
};
struct DATA1
{
int n;
};
const UINT32 DATA2_LEN = 0x10;
struct DATA2
{
char szInfo[DATA2_LEN];
};
enum E_LOG_ID
{
ELOG_HEADER,
ELOG_DATA1,
ELOG_DATA2,
};
int __stdcall ReadFunction(const UINT32 uLogId, BYTE *pBuf, UINT32 uBufLen)
{
DATA1 *pData1(NULL);
DATA2 *pData2(NULL);
LOG_HEADER* pData(NULL);
int nRet(0);
switch (uLogId)
{
default:
break;
case ELOG_DATA1:
{
ASSERT(uBufLen == sizeof(DATA1));
pData1 = (DATA1*)pBuf;
}
break;
case ELOG_DATA2:
{
ASSERT(uBufLen == sizeof(DATA2));
pData2 = (DATA2*)pBuf;
}
break;
case ELOG_HEADER:
{
ASSERT(uBufLen == LOG_HEADER_LEN);
pData = (LOG_HEADER*)pBuf;
}
break;
}
return 0;
}
int ReadLog()
{
g_log.SetFileName(_T("d:\\aa.txt"));
g_log.ReadLog(ReadFunction);
return 0;
}
int WriteLog()
{
g_log.SetFileName(_T("d:\\aa.txt"));
//写文件头
BYTE HeadBuf[LOG_HEADER_LEN] = {};
LOG_HEADER *pHeader = (LOG_HEADER*)HeadBuf;
pHeader->uVer = 2;
g_log.WriteLog(ELOG_HEADER, HeadBuf, LOG_HEADER_LEN, 0);
//写其它数据
DATA1 data1;
ZeroMemory(&data1, sizeof(data1));
data1.n = 5;
g_log.WriteLog(ELOG_DATA1, (BYTE*)&data1, sizeof(data1),1);
DATA2 data2;
ZeroMemory(&data2, sizeof(data2));
_tcscpy_s(data2.szInfo, DATA2_LEN, _T("中国"));
g_log.WriteLog(ELOG_DATA2, (BYTE*)&data2, sizeof(data2), 0);
return 0;
}