CArchive类的用法

CArchive类的用法

部分载自: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;
}

你可能感兴趣的:(CArchive类的用法)