科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航



  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

MFC 提供CArchive类实现数据的缓冲区读写,同时定义了类对象的存储与读取方案。 以下对CArchvie 的内部实现作分析(续二)。

来源:CSDN 2007年09月26日

关键字:CArchive MFC ghost

六.字符串的读写

①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;
}


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1658815

推广二维码
邮件订阅

如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

重磅专题