MFC 7 中 CString 的 >> 和 << 行为差异,以及双 '\0' 结尾字符串(如 REG_MULTI_SZ)






1.14/5 (35投票s)
2003年6月4日
1分钟阅读

172281
MFC 7 中 CString 的 >> 和 << 行为差异,以及双 '\0' 结尾字符串(如 REG_MULTI_SZ)和一个解决方法
引言
本文解释了在使用 CString 处理二进制缓冲区(使用 REG_MULTI_SZ 的 GetBuffer 或 GetBufferSetLength)以及序列化(更准确地说,是读取操作,写入操作工作正常)时,行为上的差异。 当缓冲区中间包含 '\0' 时,问题就会发生。 CArchive << 将所有缓冲区写入文件,但 CArchive >> 将文件中的所有数据按预期读取到临时缓冲区中,并使用 CString 运算符 = 将其分配给 CString。 这就是问题所在,CString 运算符 = 在 '\0' 处停止。 以下是包含错误的 MFC 代码以及尝试解决问题的解决方法。
有人可能会说,为什么这样? 使用数组。 我同意他们的观点,但是,在我的情况下,我无法使用数组。 这是我在 5 年 MFC 开发生涯中第一次必须做出这种“异端”行为,就像有些人认为的那样。
我更改了文章的标题,改为行为差异,因为人们的意见。
使用代码
这是 MFC 代码
template< typename BaseType, class StringTraits > CArchive& AFXAPI operator>>(CArchive& ar, ATL::CStringT& str) { int nCharSize; // 1 = char, 2 = wchar_t UINT nLength = UINT( AfxReadStringLength(ar, nCharSize) ); if (nCharSize == sizeof(char)) { ATL::CTempBuffer< char > pszBufferA(nLength+1); pszBufferA[nLength] = '\0'; UINT nBytesRead = ar.Read(pszBufferA, nLength*sizeof(char)); if (nBytesRead != (nLength*sizeof(char))) AfxThrowArchiveException(CArchiveException::endOfFile); str = pszBufferA; } else { ASSERT(nCharSize == sizeof(wchar_t)); ATL::CTempBuffer< wchar_t > pszBufferW( nLength+1 ); pszBufferW[nLength] = L'\0'; UINT nBytesRead = ar.Read(pszBufferW, nLength*sizeof(wchar_t)); if (nBytesRead != (nLength*sizeof(wchar_t))) AfxThrowArchiveException(CArchiveException::endOfFile); str = pszBufferW; } return ar; }
这是一个解决方法
EXPORT_LCC UINT LCC_ReadBinaryCStringFromArchive(CArchive& ar, CString& str) { ASSERT(ar.IsLoading()); UINT nBytesRead; int nCharSize; // 1 = char, 2 = wchar_t UINT nLength = UINT( AfxReadStringLength(ar, nCharSize) ); if (nCharSize == sizeof(char)) { // is UNICODE ? if nLength is 10 chars we must 5 wchar_t // to hold 10 chars if (nCharSize != sizeof(TCHAR)) nBytesRead = ar.Read(str.GetBufferSetLength(nLength / sizeof (TCHAR) + (nLength % sizeof(TCHAR))), nLength * sizeof(char)); else nBytesRead = ar.Read(str.GetBufferSetLength(nLength), nLength*sizeof(char)); if (nBytesRead != (nLength*sizeof(char))) AfxThrowArchiveException(CArchiveException::endOfFile); } else { ASSERT(nCharSize == sizeof(wchar_t)); // not is UNICODE ? if nLength is 10 w_chars we must // 20 chars to hold 10 w_chars if (nCharSize != sizeof(TCHAR)) nBytesRead = ar.Read(str.GetBufferSetLength(nLength * sizeof(TCHAR)), nLength * sizeof(wchar_t)); else nBytesRead = ar.Read(str.GetBufferSetLength(nLength), nLength*sizeof(wchar_t)); if (nBytesRead != (nLength*sizeof(wchar_t))) AfxThrowArchiveException(CArchiveException::endOfFile); } return nBytesRead; }
我知道这与重载的 CArchive 运算符 >> 的便利性并不相同,但它对我有用。 只有在需要时才使用 CString。 如果不需要,请使用数组。