六.字符串的读写 ①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