五.指定长度数据段落的读写
以下分析 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; } }
六.字符串的读写
①CArchive提供的WriteString和ReadString
字符串写 void CArchive::WriteString(LPCTSTR lpsz) { ASSERT(AfxIsValidString(lpsz)); Write(lpsz, lstrlen(lpsz) * sizeof(TCHAR)); //调用Write,将字符串对应的一段数据写入 }
字符串读(读取一行字符串) LPTSTR CArchive::ReadString(LPTSTR lpsz, UINT nMax) { // if nMax is negative (such a large number doesn''t make sense given today''s // 2gb address space), then assume it to mean "keep the newline". int nStop = (int)nMax < 0 ? -(int)nMax : (int)nMax; ASSERT(AfxIsValidAddress(lpsz, (nStop+1) * sizeof(TCHAR)));
_TUCHAR ch; int nRead = 0;
TRY { while (nRead < nStop) { *this >> ch; //读出一个字节
// stop and end-of-line (trailing ''/n'' is ignored) 遇换行—回车 if (ch == ''/n'' || ch == ''/r'') { if (ch == ''/r'') *this >> ch; // store the newline when called with negative nMax if ((int)nMax != nStop) lpsz[nRead++] = ch; break; } lpsz[nRead++] = ch; } } CATCH(CArchiveException, e) { if (e-> m_cause == CArchiveException::endOfFile) { DELETE_EXCEPTION(e); if (nRead == 0) return NULL; } else { THROW_LAST(); } } END_CATCH
lpsz[nRead] = ''/0''; return lpsz; }
ReadString到CString对象,可以多行字符 BOOL CArchive::ReadString(CString& rString) { rString = &afxChNil; // empty string without deallocating const int nMaxSize = 128; LPTSTR lpsz = rString.GetBuffer(nMaxSize); LPTSTR lpszResult; int nLen; for (;;) { lpszResult = ReadString(lpsz, (UINT)-nMaxSize); // store the newline rString.ReleaseBuffer();
// if string is read completely or EOF if (lpszResult == NULL || (nLen = lstrlen(lpsz)) < nMaxSize || lpsz[nLen-1] == ''/n'') { break; }
nLen = rString.GetLength(); lpsz = rString.GetBuffer(nMaxSize + nLen) + nLen; }
// remove ''/n'' from end of string if present lpsz = rString.GetBuffer(0); nLen = rString.GetLength(); if (nLen != 0 && lpsz[nLen-1] == ''/n'') rString.GetBufferSetLength(nLen-1);
return lpszResult != NULL; }
②使用CString对象的"<<"与">>"符读写字符串 CString定义了输入输出符,可以象基本类型的数据一样使用CArchive 的操作符定义
friend CArchive& AFXAPI operator<<(CArchive& ar, const CString& string); friend CArchive& AFXAPI operator>>(CArchive& ar, CString& string); // CString serialization code // String format: // UNICODE strings are always prefixed by 0xff, 0xfffe // if < 0xff chars: len:BYTE, TCHAR chars // if >= 0xff characters: 0xff, len:WORD, TCHAR chars // if >= 0xfffe characters: 0xff, 0xffff, len:DWORD, TCHARs
CArchive& AFXAPI operator<<(CArchive& ar, const CString& string) { // special signature to recognize unicode strings #ifdef _UNICODE ar << (BYTE)0xff; ar << (WORD)0xfffe; #endif
if (string.GetData()-> nDataLength < 255) { ar << (BYTE)string.GetData()-> nDataLength; } else if (string.GetData()-> nDataLength < 0xfffe) { ar << (BYTE)0xff; ar << (WORD)string.GetData()-> nDataLength; } else { ar << (BYTE)0xff; ar << (WORD)0xffff; ar << (DWORD)string.GetData()-> nDataLength; } ar.Write(string.m_pchData, string.GetData()-> nDataLength*sizeof(TCHAR)); return ar; }
// return string length or -1 if UNICODE string is found in the archive AFX_STATIC UINT AFXAPI _AfxReadStringLength(CArchive& ar) { DWORD nNewLen;
// attempt BYTE length first BYTE bLen; ar >> bLen;
if (bLen < 0xff) return bLen;
// attempt WORD length WORD wLen; ar >> wLen; if (wLen == 0xfffe) { // UNICODE string prefix (length will follow) return (UINT)-1; } else if (wLen == 0xffff) { // read DWORD of length ar >> nNewLen; return (UINT)nNewLen; } else return wLen; }
CArchive& AFXAPI operator>>(CArchive& ar, CString& string) { #ifdef _UNICODE int nConvert = 1; // if we get ANSI, convert #else int nConvert = 0; // if we get UNICODE, convert #endif
UINT nNewLen = _AfxReadStringLength(ar); if (nNewLen == (UINT)-1) { nConvert = 1 - nConvert; nNewLen = _AfxReadStringLength(ar); ASSERT(nNewLen != -1); }
// set length of string to new length UINT nByteLen = nNewLen; #ifdef _UNICODE string.GetBufferSetLength((int)nNewLen); nByteLen += nByteLen * (1 - nConvert); // bytes to read #else nByteLen += nByteLen * nConvert; // bytes to read if (nNewLen == 0) string.GetBufferSetLength(0); else string.GetBufferSetLength((int)nByteLen+nConvert); #endif
// read in the characters if (nNewLen != 0) { ASSERT(nByteLen != 0);
// read new data if (ar.Read(string.m_pchData, nByteLen) != nByteLen) AfxThrowArchiveException(CArchiveException::endOfFile);
// convert the data if as necessary if (nConvert != 0) { #ifdef _UNICODE CStringData* pOldData = string.GetData(); LPSTR lpsz = (LPSTR)string.m_pchData; #else CStringData* pOldData = string.GetData(); LPWSTR lpsz = (LPWSTR)string.m_pchData; #endif lpsz[nNewLen] = ''/0''; // must be NUL terminated string.Init(); // don''t delete the old data string = lpsz; // convert with operator=(LPWCSTR) CString::FreeData(pOldData); } } return ar; }  
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |