1.先贴上该类:
{
protected:
enum SchemaMapReservedRefs { objTypeArrayRef = 1 };
enum LoadArrayObjType{ typeUndefined = 0, typeCRuntimeClass = 1, typeCObject = 2 };
public:
// Flag values
enum Mode { store = 0, load = 1, bNoFlushOnDelete = 2, bNoByteSwap = 4 };
CArchive(CFile* pFile, UINT nMode, int nBufSize = 4096, void* lpBuf = NULL);
~CArchive();
// Attributes
BOOL IsLoading() const;
BOOL IsStoring() const;
BOOL IsByteSwapping() const;
BOOL IsBufferEmpty() const;
CFile* GetFile() const;
UINT GetObjectSchema(); // only valid when reading a CObject*
void SetObjectSchema(UINT nSchema);
// pointer to document being serialized -- must set to serialize
// COleClientItems in a document!
CDocument* m_pDocument;
// Operations
UINT Read(void* lpBuf, UINT nMax);
void EnsureRead(void *lpBuf, UINT nCount);
void Write(const void* lpBuf, UINT nMax);
void Flush();
void Close();
void Abort(); // close and shutdown without exceptions
// reading and writing strings
void WriteString(LPCTSTR lpsz);
LPTSTR ReadString(_Out_z_cap_(nMax+1) LPTSTR lpsz, _In_ UINT nMax);
BOOL ReadString(CString& rString);
public:
// Object I/O is pointer based to avoid added construction overhead.
// Use the Serialize member function directly for embedded objects.
friend CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb);
friend CArchive& AFXAPI operator>>(CArchive& ar, CObject*& pOb);
friend CArchive& AFXAPI operator>>(CArchive& ar, const CObject*& pOb);
// insertion operations
CArchive& operator<<(BYTE by);
CArchive& operator<<(WORD w);
CArchive& operator<<(LONG l);
CArchive& operator<<(DWORD dw);
CArchive& operator<<(float f);
CArchive& operator<<(double d);
CArchive& operator<<(LONGLONG dwdw);
CArchive& operator<<(ULONGLONG dwdw);
CArchive& operator<<(int i);
CArchive& operator<<(short w);
CArchive& operator<<(char ch);
#ifdef _NATIVE_WCHAR_T_DEFINED
CArchive& operator<<(wchar_t ch);
#endif
CArchive& operator<<(unsigned u);
template < typename BaseType , bool t_bMFCDLL>
CArchive& operator<<(const ATL::CSimpleStringT<BaseType, t_bMFCDLL>& str);
template< typename BaseType, class StringTraits >
CArchive& operator<<(const ATL::CStringT<BaseType, StringTraits>& str);
template < typename BaseType , bool t_bMFCDLL>
CArchive& operator>>(ATL::CSimpleStringT<BaseType, t_bMFCDLL>& str);
template< typename BaseType, class StringTraits >
CArchive& operator>>(ATL::CStringT<BaseType, StringTraits>& str);
CArchive& operator<<(bool b);
// extraction operations
CArchive& operator>>(BYTE& by);
CArchive& operator>>(WORD& w);
CArchive& operator>>(DWORD& dw);
CArchive& operator>>(LONG& l);
CArchive& operator>>(float& f);
CArchive& operator>>(double& d);
CArchive& operator>>(LONGLONG& dwdw);
CArchive& operator>>(ULONGLONG& dwdw);
CArchive& operator>>(int& i);
CArchive& operator>>(short& w);
CArchive& operator>>(char& ch);
#ifdef _NATIVE_WCHAR_T_DEFINED
CArchive& operator>>(wchar_t& ch);
#endif
CArchive& operator>>(unsigned& u);
CArchive& operator>>(bool& b);
// object read/write
CObject* ReadObject(const CRuntimeClass* pClass);
void WriteObject(const CObject* pOb);
// advanced object mapping (used for forced references)
void MapObject(const CObject* pOb);
// advanced versioning support
void WriteClass(const CRuntimeClass* pClassRef);
CRuntimeClass* ReadClass(const CRuntimeClass* pClassRefRequested = NULL,
UINT* pSchema = NULL, DWORD* pObTag = NULL);
void SerializeClass(const CRuntimeClass* pClassRef);
// advanced operations (used when storing/loading many objects)
void SetStoreParams(UINT nHashSize = 2053, UINT nBlockSize = 128);
void SetLoadParams(UINT nGrowBy = 1024);
void EnsureSchemaMapExists(CArray<LoadArrayObjType, const LoadArrayObjType&>** ppObjTypeArray = NULL);
// Implementation
public:
BOOL m_bForceFlat; // for COleClientItem implementation (default TRUE)
BOOL m_bDirectBuffer; // TRUE if m_pFile supports direct buffering
BOOL m_bBlocking; // TRUE if m_pFile can block for unbounded periods of time
void FillBuffer(UINT nBytesNeeded);
void CheckCount(); // throw exception if m_nMapCount is too large
// special functions for reading and writing (16-bit compatible) counts
DWORD_PTR ReadCount();
void WriteCount(DWORD_PTR dwCount);
// public for advanced use
UINT m_nObjectSchema;
CString m_strFileName;
protected:
// archive objects cannot be copied or assigned
CArchive(const CArchive& arSrc);
void operator=(const CArchive& arSrc);
BOOL m_nMode;
BOOL m_bUserBuf;
int m_nBufSize;
CFile* m_pFile;
BYTE* m_lpBufCur;
BYTE* m_lpBufMax;
BYTE* m_lpBufStart;
// array/map for CObject* and CRuntimeClass* load/store
UINT m_nMapCount;
union
{
CPtrArray* m_pLoadArray;
CMapPtrToPtr* m_pStoreMap;
};
// map to keep track of mismatched schemas
CMapPtrToPtr* m_pSchemaMap;
// advanced parameters (controls performance with large archives)
UINT m_nGrowSize;
UINT m_nHashSize;
};
缓冲区指针 BYTE* m_lpBufStart,指向缓冲区,这个缓冲区有可能是底层CFile(如派生类CMemFile)对象提供的,但一般是CArchive自己建立的。
缓冲区尾部指针 BYTE* m_lpBufMax;
缓冲区当前位置指针 BYTE* m_lpBufCur;
初始化时,如果是读模式,当前位置在尾部,如果是写模式,当前位置在头部:m_lpBufCur = (IsLoading()) ? m_lpBufMax : m_lpBufStart;
其中_AFX_INLINE BOOL CArchive::IsLoading() const
{ return (m_nMode & CArchive::load) != 0; }用来判断是输入还是输出
下面是构造函数的源代码:
CArchive::CArchive(CFile* pFile, UINT nMode, int nBufSize, void* lpBuf)
{
ASSERT_VALID(pFile);
if(pFile == NULL)
{
AfxThrowInvalidArgException();
}
m_strFileName = pFile->GetFilePath();
// initialize members not dependent on allocated buffer
m_nMode = nMode;
m_pFile = pFile;
m_pSchemaMap = NULL;
m_pLoadArray = NULL;
m_pDocument = NULL;
m_bForceFlat = TRUE;
m_nObjectSchema = (UINT)-1; // start with invalid schema
if (IsStoring())
m_nGrowSize = nBlockSize;
else
m_nGrowSize = nGrowSize;
m_nHashSize = nHashSize;
// initialize the buffer. minimum size is 128
m_lpBufStart = (BYTE*)lpBuf;
m_bUserBuf = TRUE;
m_bDirectBuffer = FALSE;
m_bBlocking = m_pFile->GetBufferPtr(CFile::bufferCheck)&CFile::bufferBlocking;
if (nBufSize < nBufSizeMin)
{
// force use of private buffer of minimum size
m_nBufSize = nBufSizeMin;
m_lpBufStart = NULL;
}
else
m_nBufSize = nBufSize;
nBufSize = m_nBufSize;
if (m_lpBufStart == NULL)
{
// check for CFile providing buffering support
m_bDirectBuffer = m_pFile->GetBufferPtr(CFile::bufferCheck)&CFile::bufferDirect;
if (!m_bDirectBuffer)
{
// no support for direct buffering, allocate new buffer
m_lpBufStart = new BYTE[m_nBufSize];
m_bUserBuf = FALSE;
}
else
{
// CFile* supports direct buffering!
nBufSize = 0; // will trigger initial FillBuffer
}
}
if (!m_bDirectBuffer)
{
ASSERT(m_lpBufStart != NULL);
ASSERT(AfxIsValidAddress(m_lpBufStart, nBufSize, IsStoring()));
}
m_lpBufMax = m_lpBufStart + nBufSize;
m_lpBufCur = (IsLoading()) ? m_lpBufMax : m_lpBufStart;
ASSERT(m_pStoreMap == NULL); // same as m_pLoadArray
}