程序代码
#include <afxwin.h> int _tmain(int argc, _TCHAR* argv[]) { CFile file("file.dat", CFile::modeReadWrite | CFile::modeCreate); CArchive ar(&file, CArchive::store); SIZE size = { 100, 200 }; ar<<size; return 0; }
对于MFC基本类型,如CString、CTime、CTimeSpan、COleVariant、COleCurrency、COldDateTime、COleDateTimeSpan、CSize、CPoint、CSize、SIZE、POINT 和 RECT。MFC都重载了<<运算符,使对它们的串行化很easy。
本文介绍的是对SIZE结构的串行化,它是调用CArchive::Write()函数实现的。
CArchive& operator<<(CArchive& ar, SIZE size) { ar.Write(&size, sizeof(SIZE)); return ar; }
CArchive::Write()函数接收两个参数,一个指针指向待写入缓冲区,一个待写入数据量。
// lpBuf为待写入数据指针,nMax为待写入字节数。 void CArchive::Write(const void* lpBuf, UINT nMax) { if (nMax == 0) return; if(lpBuf == NULL) return; if(!IsStoring()) // 如果不是存储过程,抛出异常 AfxThrowArchiveException(CArchiveException::readOnly,m_strFileName); // copy to buffer if possible UINT nTemp = min(nMax, (UINT)(m_lpBufMax - m_lpBufCur)); // 取nMax和缓冲区剩余容量较小值,尽可能塞满缓冲区。 Checked::memcpy_s(m_lpBufCur, (size_t)(m_lpBufMax - m_lpBufCur), lpBuf, nTemp); // 将nTemp字节的数据拷贝到缓冲。 m_lpBufCur += nTemp; lpBuf = (BYTE*)lpBuf + nTemp; nMax -= nTemp; if (nMax > 0) { // 拷贝一次之后还有剩余,说明当前缓冲区已满,首先调用CArchive::Flush()函数刷新缓冲。 // 如果是向文件写数据,则将当前CArchive缓冲的数据写到文件中。如果是直接缓冲,则提交当前缓冲区,获取下一个缓冲区界面。 Flush(); // flush the full buffer // 如果新获得的缓冲区仍不足以容纳剩余的数据,则将m_nBufferSize整数倍的数据直接写入。 nTemp = nMax - (nMax % m_nBufSize); m_pFile->Write(lpBuf, nTemp); lpBuf = (BYTE*)lpBuf + nTemp; nMax -= nTemp; if (m_bDirectBuffer) { // 直接缓冲,重新获取缓冲区界面 // sync up direct mode buffer to new file position VERIFY(m_pFile->GetBufferPtr(CFile::bufferWrite, m_nBufSize, (void**)&m_lpBufStart, (void**)&m_lpBufMax) == (UINT)m_nBufSize); m_lpBufCur = m_lpBufStart; } // 拷贝剩下的数据到当前缓冲区。 Checked::memcpy_s(m_lpBufCur, nMax, lpBuf, nMax); m_lpBufCur += nMax; } }
CFile::Write是通过API WriteFile实现的,将数据写入到文件中。而CMemFile::Write则是简单的拷贝缓冲区,更新位置信息。