部分載自:http://www.tongyi.net/develop/mfc/1003840.html
CArchive類是使用了緩沖區,即一段內存空間作為臨時數據存儲地,對CArchive的讀寫都先依次排列到此緩沖區,當緩沖區滿或用戶要求時,將此段整理后的數據讀寫到指定的存儲煤質。
一般來說,CArchive封裝了對該緩沖區的操作,它的好處是可以少劃動硬盤以及提高運行速度。不過對于使用MFC來說,是一個很好的封裝??纯雌鋵ψx寫的操作,可見在實際編程上是非常容易出錯的。對于這樣的類,一定要封裝好,作為一個公用函數或公用類調用,否則在實際中像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;
}