FMD开发文集 -- CArchive原理
2010-03-28 20:34:54 来源:WEB开发网五.指定长度数据段落的读写
以下分析
UINT Read(void* lpBuf, UINT nMax); 读取长度为nMax的数据
void Write(const void* lpBuf, UINT nMax); 写入指定长度nMax的数据
对于大段数据的读写,先使用当前缓冲区中的内容或空间读取或写入,若这些空间够用了,则结束。
否则,从剩余的数据中找出最大的缓冲区整数倍大小的一块数据,直接读写到存储煤质(不反复使用缓冲区)。
剩余的余数部分,再使用缓冲区读写。
(说明:缓冲区读写的主要目的是将零散的数据以缓冲区大小为尺度来处理。对于大型数据,其中间的部分,不是零散的数据,使用缓冲区已经没有意思,故直接读写)
①读取
UINT CArchive::Read(void* lpBuf, UINT nMax)
②保存,写入
{
ASSERT_VALID(m_pFile);
if (nMax == 0)
return 0;
UINT nMaxTemp = nMax; //还需要读入的长度,读入一部分,就减相应数值,直到此数值变为零
//处理当前缓冲区中剩余部分。
//如果要求读入字节小于缓冲区中剩余部分,则第一部分为要求读入的字节数,
//否则读入全部剩余部分
UINT nTemp = min(nMaxTemp, (UINT)(m_lpBufMax - m_lpBufCur));
memcpy(lpBuf, m_lpBufCur, nTemp);
m_lpBufCur += nTemp;
lpBuf = (BYTE*)lpBuf + nTemp; //移动读出内容所在区域的指针
nMaxTemp -= nTemp;
//当前缓冲区中剩余部分不够要求读入的长度。
//还有字节需要读,则需要根据需要执行若干次填充缓冲区,读出,直到读出指定字节。
if (nMaxTemp != 0)
{
//计算出去除尾数部分的字节大小(整数个缓冲区大小)
//对于这些部分,字节从文件对象中读出,放到输出缓冲区
nTemp = nMaxTemp - (nMaxTemp % m_nBufSize);
UINT nRead = 0;
UINT nLeft = nTemp;
UINT nBytes;
do
{
nBytes = m_pFile-> Read(lpBuf, nLeft); //要求读入此整数缓冲区部分大小
lpBuf = (BYTE*)lpBuf + nBytes;
nRead += nBytes;
nLeft -= nBytes;
}
while ((nBytes > 0) && (nLeft > 0)); 知道读入了预定大小,或到达文件尾
nMaxTemp -= nRead;
if (nRead == nTemp) //读入的字节等于读入的整数倍部分 该读最后的余数部分了
{
// 建立装有此最后余数部分的内容的CArchive的工作缓冲区。
if (!m_bDirectBuffer)
{
UINT nLeft = max(nMaxTemp, (UINT)m_nBufSize);
UINT nBytes;
BYTE* lpTemp = m_lpBufStart;
nRead = 0;
do
{
nBytes = m_pFile-> Read(lpTemp, nLeft); //从文件中读入到CArchive缓冲区
lpTemp = lpTemp + nBytes;
nRead += nBytes;
nLeft -= nBytes;
}
while ((nBytes > 0) && (nLeft > 0) && nRead < nMaxTemp);
m_lpBufCur = m_lpBufStart;
m_lpBufMax = m_lpBufStart + nRead;
}
else
{
nRead = m_pFile-> GetBufferPtr(CFile::bufferRead, m_nBufSize,
(void**)&m_lpBufStart, (void**)&m_lpBufMax);
ASSERT(nRead == (UINT)(m_lpBufMax - m_lpBufStart));
m_lpBufCur = m_lpBufStart;
}
//读出此剩余部分到输出
nTemp = min(nMaxTemp, (UINT)(m_lpBufMax - m_lpBufCur));
memcpy(lpBuf, m_lpBufCur, nTemp);
m_lpBufCur += nTemp;
nMaxTemp -= nTemp;
}
}
return nMax - nMaxTemp;
}void CArchive::Write(const void* lpBuf, UINT nMax)
{
if (nMax == 0)
return;
//读入可能的部分到缓冲区当前的剩余部分
UINT nTemp = min(nMax, (UINT)(m_lpBufMax - m_lpBufCur));
memcpy(m_lpBufCur, lpBuf, nTemp);
m_lpBufCur += nTemp;
lpBuf = (BYTE*)lpBuf + nTemp;
nMax -= nTemp;
if (nMax > 0) //还有未写入的部分
{
Flush(); //将当前缓冲区写入到存储煤质
//计算出整数倍缓冲区大小的字节数
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);
ASSERT((UINT)m_nBufSize == (UINT)(m_lpBufMax - m_lpBufStart));
m_lpBufCur = m_lpBufStart;
}
// copy remaining to active buffer
ASSERT(nMax < (UINT)m_nBufSize);
ASSERT(m_lpBufCur == m_lpBufStart);
memcpy(m_lpBufCur, lpBuf, nMax);
m_lpBufCur += nMax;
}
}
- ››开发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新特性
更多精彩
赞助商链接