FMD开发文集 -- CArchive原理
2010-03-28 20:34:54 来源:WEB开发网双字的插入(写)
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;
}
以上操作中,当缓冲区将插入满或缓冲区将提取空时,都将对缓冲区进行更新处理。
缓冲区将插入满时调用Flush();void CArchive::Flush()
缓冲区将提取空,会调用FillBuffer。 nBytesNeeded为当前剩余部分上尚有用的字节
{
ASSERT_VALID(m_pFile);
ASSERT(m_bDirectBuffer || m_lpBufStart != NULL);
ASSERT(m_bDirectBuffer || m_lpBufCur != NULL);
ASSERT(m_lpBufStart == NULL ||
AfxIsValidAddress(m_lpBufStart, m_lpBufMax - m_lpBufStart, IsStoring()));
ASSERT(m_lpBufCur == NULL ||
AfxIsValidAddress(m_lpBufCur, m_lpBufMax - m_lpBufCur, IsStoring()));
if (IsLoading())
{
// unget the characters in the buffer, seek back unused amount
if (m_lpBufMax != m_lpBufCur)
m_pFile-> Seek(-(m_lpBufMax - m_lpBufCur), CFile::current);
m_lpBufCur = m_lpBufMax; // 指向尾
}
else //写模式
{
if (!m_bDirectBuffer)
{
// 内容写入到文件
if (m_lpBufCur != m_lpBufStart)
m_pFile-> Write(m_lpBufStart, m_lpBufCur - m_lpBufStart);
}
else
{
//如果是直接针对内存区域的的(例如CMemFile中) (只需移动相关指针,指向新的一块内存)
if (m_lpBufCur != m_lpBufStart)
m_pFile-> GetBufferPtr(CFile::bufferCommit, m_lpBufCur - m_lpBufStart);
// get next buffer
VERIFY(m_pFile-> GetBufferPtr(CFile::bufferWrite, m_nBufSize,
(void**)&m_lpBufStart, (void**)&m_lpBufMax) == (UINT)m_nBufSize);
ASSERT((UINT)m_nBufSize == (UINT)(m_lpBufMax - m_lpBufStart));
}
m_lpBufCur = m_lpBufStart; //指向缓冲区首
}
}void CArchive::FillBuffer(UINT nBytesNeeded)
{
ASSERT_VALID(m_pFile);
ASSERT(IsLoading());
ASSERT(m_bDirectBuffer || m_lpBufStart != NULL);
ASSERT(m_bDirectBuffer || m_lpBufCur != NULL);
ASSERT(nBytesNeeded > 0);
ASSERT(nBytesNeeded <= (UINT)m_nBufSize);
ASSERT(m_lpBufStart == NULL ||
AfxIsValidAddress(m_lpBufStart, m_lpBufMax - m_lpBufStart, FALSE));
ASSERT(m_lpBufCur == NULL ||
AfxIsValidAddress(m_lpBufCur, m_lpBufMax - m_lpBufCur, FALSE));
UINT nUnused = m_lpBufMax - m_lpBufCur;
ULONG nTotalNeeded = ((ULONG)nBytesNeeded) + nUnused;
// 从文件中读取
if (!m_bDirectBuffer)
{
ASSERT(m_lpBufCur != NULL);
ASSERT(m_lpBufStart != NULL);
ASSERT(m_lpBufMax != NULL);
if (m_lpBufCur > m_lpBufStart)
{
//保留剩余的尚未处理的部分,将它们移动到头
if ((int)nUnused > 0)
{
memmove(m_lpBufStart, m_lpBufCur, nUnused);
m_lpBufCur = m_lpBufStart;
m_lpBufMax = m_lpBufStart + nUnused;
}
// read to satisfy nBytesNeeded or nLeft if possible
UINT nRead = nUnused;
UINT nLeft = m_nBufSize-nUnused;
UINT nBytes;
BYTE* lpTemp = m_lpBufStart + nUnused;
do
{
nBytes = m_pFile-> Read(lpTemp, nLeft);
lpTemp = lpTemp + nBytes;
nRead += nBytes;
nLeft -= nBytes;
}
while (nBytes > 0 && nLeft > 0 && nRead < nBytesNeeded);
m_lpBufCur = m_lpBufStart;
m_lpBufMax = m_lpBufStart + nRead;
}
}
else
{
// 如果是针对内存区域(CMemFile),移动相关指针,指向新的一块内存
if (nUnused != 0)
m_pFile-> Seek(-(LONG)nUnused, CFile::current);
UINT nActual = m_pFile-> GetBufferPtr(CFile::bufferRead, m_nBufSize,
(void**)&m_lpBufStart, (void**)&m_lpBufMax);
ASSERT(nActual == (UINT)(m_lpBufMax - m_lpBufStart));
m_lpBufCur = m_lpBufStart;
}
// not enough data to fill request?
if ((ULONG)(m_lpBufMax - m_lpBufCur) < nTotalNeeded)
AfxThrowArchiveException(CArchiveException::endOfFile);
}
- ››开发Android 日历教程
- ››开发学院总结 Win 8实用技巧大全
- ››开发学院原创教程:把win8的IE10放桌面上方法(非...
- ››开发者眼中的Windows Phone和Android
- ››开发学院教你用SQL 语句最快速清空MySQL 数据表的...
- ››开发一个自己的HTML在线编辑器(一)
- ››开发一个自己的HTML在线编辑器(二)
- ››开发者在App Store上赚的钱比在Android Market上多...
- ››开发者应深入学习的10个Android开源应用项目
- ››开发移动 Web Ajax 应用
- ››开发者眼中的iPhone与Android
- ››开发者或想使用的10个Android2.2新特性
更多精彩
赞助商链接