部分载自:http://www.tongyi.net/develop/mfc/1003840.html
CArchive类是使用了缓冲区,即一段内存空间作为临时数据存储地,对CArchive的读写都先依次排列到此缓冲区,当缓冲区满或用户要求时,将此段整理后的数据读写到指定的存储煤质。
一般来说,CArchive封装了对该缓冲区的操作,它的好处是可以少划动硬盘以及提高运行速度。不过对于使用MFC来说,是一个很好的封装。看看其对读写的操作,可见在实际编程上是非常容易出错的。对于这样的类,一定要封装好,作为一个公用函数或公用类调用,否则在实际中像c那样散在代码的各个地方的话,恐怕有时头会大。
有时我想,如果编程在这些地方磨洋工的话,恐怕一个大的工程软件写起来得好长时间。所以说尽量已组件的方式,类的思路来组合前人的算法,技巧也是一种编程的进步。
所下列看其对指针的娴熟操作(也是往往出错的啊),
例如双字的插入(写)
CArchive& CArchive::operator<<(DWORD dw) { if (m_lpBufCur + sizeof(DWORD) > m_lpBufMax) //缓冲区空间不够 Flush(); //缓冲区内容提交到实际存储煤质。 if (!(m_nMode & bNoByteSwap)) _AfxByteSwap(dw, m_lpBufCur); //处理字节顺序 else *(DWORD*)m_lpBufCur = dw; //添入缓冲区 m_lpBufCur += sizeof(DWORD); //移动当前指针 return *this; }
双字的提取(读)
CArchive& CArchive::operator>>(DWORD& dw) { if (m_lpBufCur + sizeof(DWORD) > m_lpBufMax) //缓冲区要读完了 FillBuffer(sizeof(DWORD) - (UINT)(m_lpBufMax - m_lpBufCur)); //重新读入内容到缓冲区 dw = *(DWORD*)m_lpBufCur; //读取双字 m_lpBufCur += sizeof(DWORD); //移动当前位置指针 if (!(m_nMode & bNoByteSwap)) _AfxByteSwap(dw, (BYTE*)&dw); //处理字节顺序 return *this; }
内部指针
缓冲区指针 BYTE* m_lpBufStart,指向缓冲区,这个缓冲区有可能是底层CFile(如派生类CMemFile)对象提供的,但一般是CArchive自己建立的。
缓冲区尾部指针 BYTE* m_lpBufMax;
缓冲区当前位置指针 BYTE* m_lpBufCur;
初始化时,读模式,当前位置在尾部,是写模式,当前位置在头部:
m_lpBufCur = (IsLoading()) ? m_lpBufMax : m_lpBufStart;
这里粘贴一个日志文件的类文件中使用CArchive作为内部操作的例子吧。利用CArchive去Flush,Write,Open,这里先把CArchive的参量列出:
CArchive(CFile* pFile, UINT nMode, int nBufSize = 4096, void* lpBuf = NULL);
class CLogFile
{
protected:
int m_nCachBuffSize;
int m_nCurentBuffSize;
char * m_lpCachBuff;
CString m_fileName;
CArchive *m_pArchive; //作为文件读写到内存的实际操作。
CFile m_file;
CRITICAL_SECTION m_csFile;
SYSTEMTIME m_tmCurTime; //当前时间
SYSTEMTIME m_tmLastTime; //上次日志时间
public:
void Open(char *fileName);
void Close();
void Wirte(char * buff ,int size=0);
void WriteLog(char *szLog, int size =0);
void Flush();
CLogFile() ;
~CLogFile() ;
};
***************************************************
#include "stdafx.h"
#include "LogFile.h"
#include "pubfunc.h"
CLogFile :: CLogFile()
{
::InitializeCriticalSection(&m_csFile);
m_pArchive = NULL;
m_fileName = "";
m_lpCachBuff = new char[MAX_LOG_BUFF + 1 ]; //作为内存缓冲区
m_nCachBuffSize = MAX_LOG_BUFF ;
m_nCurentBuffSize = 0;
}
CLogFile :: ~CLogFile()
{
if(m_pArchive)
{
m_pArchive->Flush();
m_file.Close();
delete m_pArchive;
m_pArchive= NULL;
}
if(m_lpCachBuff)
{
delete []m_lpCachBuff;
}
::DeleteCriticalSection(&m_csFile);
}
void CLogFile::WriteLog(char *szLog, int size)
{
if (size == 0)
size = strlen(szLog);
Wirte(szLog , size);
}
void CLogFile::Flush()
{
EnterCriticalSection(&m_csFile);
if(m_pArchive)
{
m_pArchive->Flush();
m_nCurentBuffSize=0;
}
LeaveCriticalSection(&m_csFile);
}
void CLogFile::Wirte(char * buff ,int size)
{
EnterCriticalSection(&m_csFile);
GetLocalTime(&m_tmCurTime);
char szTime[128]={0};
int timelen = sprintf(szTime,"\r\n%04d-%02d-%02d %02d:%02d:%02d\r\n\r\n",m_tmCurTime.wYear,m_tmCurTime.wMonth,m_tmCurTime.wDay,m_tmCurTime.wHour,m_tmCurTime.wMinute,m_tmCurTime.wSecond);
if (m_tmCurTime.wYear != m_tmLastTime.wYear
||m_tmCurTime.wMonth != m_tmLastTime.wMonth
||m_tmCurTime.wDay != m_tmLastTime.wDay)
{
if(m_pArchive)
{
m_pArchive->Flush();
m_file.Close();
}
char szFile[256],szPath[256];
GetLocalTime(&m_tmLastTime);
//GetAppPath(szPath);
szPath = "自己抓取当前目录吧,出错我不管了";
if(m_pArchive)
{
delete m_pArchive;
}
if(m_fileName.IsEmpty())
{
sprintf(szFile,"%s\\Log\\%d-%02d-%02d_%s.log",szPath,m_tmLastTime.wYear,m_tmLastTime.wMonth,m_tmLastTime.wDay,(LPTSTR)(LPCTSTR)m_fileName);
}else
{
sprintf(szFile,"%s\\Log\\%d-%02d-%02d.log",szPath,m_tmLastTime.wYear,m_tmLastTime.wMonth,m_tmLastTime.wDay);
}
if(m_file.Open(szFile,CFile::modeCreate|CFile::modeNoTruncate|CFile::modeReadWrite|CFile::shareDenyNone,0))
{
m_file.SeekToEnd();
m_pArchive = new CArchive(&m_file,CArchive::store,m_nCachBuffSize,m_lpCachBuff);
int totalsize = timelen + size ;
if( totalsize > ( m_nCachBuffSize - m_nCurentBuffSize) )
{
m_pArchive->Flush();
m_pArchive->Write( szTime ,timelen );
m_pArchive->Flush();
for ( int i =0 ; i < totalsize/m_nCachBuffSize;i++)
{
m_pArchive->Write(buff+m_nCachBuffSize * i ,m_nCachBuffSize);
m_pArchive->Flush();
}
m_nCurentBuffSize = totalsize - m_nCachBuffSize * (totalsize/m_nCachBuffSize);
m_pArchive->Write(buff+m_nCachBuffSize * (totalsize/m_nCachBuffSize) * i ,m_nCurentBuffSize);
m_lpCachBuff[m_nCurentBuffSize+1] = 0;
}
else
{
m_pArchive->Write( szTime ,timelen );
m_pArchive->Write( buff ,size );
m_nCurentBuffSize=m_nCurentBuffSize+ totalsize;
m_lpCachBuff[m_nCurentBuffSize+1]=0;
}
}
else
{
m_pArchive = NULL;
}
}
else
{//续写log文件
if(m_pArchive)
{
int totalsize = timelen + size ;
if( totalsize > ( m_nCachBuffSize -m_nCurentBuffSize) )
{
m_pArchive->Flush();
m_pArchive->Write( szTime ,timelen );
m_pArchive->Flush();
for ( int i =0 ; i < totalsize/m_nCachBuffSize;i++)
{
m_pArchive->Write(buff+m_nCachBuffSize * i ,m_nCachBuffSize);
m_pArchive->Flush();
}
m_nCurentBuffSize = totalsize - m_nCachBuffSize * (totalsize/m_nCachBuffSize);
m_pArchive->Write(buff+m_nCachBuffSize * (totalsize/m_nCachBuffSize) * i ,m_nCurentBuffSize);
m_lpCachBuff[m_nCurentBuffSize + 1]=0;
}
else
{
m_pArchive->Write( szTime ,timelen );
m_pArchive->Write( buff, size );
m_nCurentBuffSize = m_nCurentBuffSize + totalsize;
m_lpCachBuff[m_nCurentBuffSize+1]=0;
}
}
}
LeaveCriticalSection(&m_csFile);
}
/*
fileName 文件名称
*/
void CLogFile::Open( char *fileName)
{
m_nCurentBuffSize = 0;
::InitializeCriticalSection(&m_csFile);
char szFile[256],szPath[256];
GetLocalTime(&m_tmLastTime);
// GetAppPath(szPath);
szPath = "把szPath修改为类变量吧,然后找个获取当前目录的函数,改动下吧,白给你用这个类不看看也是不行的"
if(fileName == 0 || fileName[0] == 0)
{
sprintf(szFile,"%s\\Log\\%d-%02d-%02d.log",szPath,m_tmLastTime.wYear,m_tmLastTime.wMonth,m_tmLastTime.wDay);
}
else
{
m_fileName = fileName;
sprintf(szFile,"%s\\Log\\%d-%02d-%02d_%s.log",szPath,m_tmLastTime.wYear,m_tmLastTime.wMonth,m_tmLastTime.wDay,fileName);
}
if(m_file.Open(szFile,CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite|CFile::shareDenyNone,0))
{
m_pArchive = new CArchive(&m_file,CArchive::store,m_nCachBuffSize, m_lpCachBuff);
}
else
{
m_pArchive = NULL;
}
}
void CLogFile::Close()
{
if(m_pArchive)
{
m_pArchive->Flush();
m_file.Close();
delete m_pArchive;
m_pArchive= NULL;
}
m_nCurentBuffSize = 0;
}