我正在尝试使用LPSTREAM将文本读入CString,但它似乎没有正常工作,这是我正在调用的代码:
static HRESULT UTL_ReadStreamTxt(MyStorage* pSrcStg, const char* pszStream, CString* myCStr, int size)
{
HRESULT hrRet = STG_E_INVALIDPARAMETER;
LPSTREAM lpSrc = NULL;
ULONG ul;
TRY
{
USES_CONVERSION;
HRESULT hrSrc = pSrcStg->GetStg()->OpenStream(CT2COLE(strSrc),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpSrc);
if (hrSrc != NOERROR)
{
hrRet = hrSrc;
}
else
{
hrRet = lpSrc->Read(&myCStr, size, NULL); // Read into CString
}
}
CATCH_ALL(e)
{
hrRet = STG_E_UNKNOWN;
}
END_CATCH_ALL
_AfxRelease((LPUNKNOWN*)&lpSrc);
return hrRet;
}
当它读入字符串时,Visual Studio会说CString中的数据已损坏。
复合存储的流内容如下:
abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
我不完全确定我正确使用Read(),如何解决此问题?
答案 0 :(得分:1)
主要问题是您将错误的指针传递给Read()
。您正在传递myCStr
参数本身的内存地址,而不是CString
的地址,而不是CString
所拥有的字符缓冲区的内存地址。代码编译只是因为Read()
使用指向缓冲区的简单void*
指针,而任何指针都可以隐式转换为void*
。
另请注意,CString
基于TCHAR
,它会映射到char
或wchar_t
,具体取决于您是为ANSI / MBCS还是Unicode编译项目。因此,直接从流中读取CString
只会在以下情况下正常工作:
该流包含ANSI字符,TCHAR
映射到char
。
该流包含UTF-16字符,TCHAR
映射到wchar_t
。
如果流的字符类型与CString
使用的字符类型不匹配,则必须首先将流读入中间缓冲区,然后将其转换为TCHAR
,然后才能将其存储到CString
。
尝试更像这样的事情:
static HRESULT UTL_ReadStreamTxt(MyStorage* pSrcStg, const char* pszStream, CString* myCStr, int size)
{
HRESULT hrRet = STG_E_INVALIDPARAMETER;
LPSTREAM lpSrc = NULL;
ULONG ul;
LPVOID buffer;
TRY
{
USES_CONVERSION;
HRESULT hrSrc = pSrcStg->GetStg()->OpenStream(CT2COLE(strSrc),
NULL,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0,
&lpSrc);
if (hrSrc != S_OK)
{
hrRet = hrSrc;
}
else
{
// if the stream's character type matches TCHAR...
buffer = myCStr->GetBuffer(size / sizeof(TCHAR));
hrRet = lpSrc->Read(buffer, size, &ul);
myCStr->ReleaseBuffer(ul / sizeof(TCHAR));
// else, if the stream's character type is 'char' and TCHAR is 'wchar_t'...
CStringA tmp;
buffer = tmp.GetBuffer(size);
hrRet = lpSrc->Read(buffer, size, &ul);
tmp.ReleaseBuffer(ul);
*myCStr = CString((LPSTR)tmp, tmp.GetLength());
// else, if the stream's character type is 'wchar_t' and TCHAR is 'char'...
CStringW tmp;
buffer = tmp.GetBuffer(size / sizeof(wchar_t));
hrRet = lpSrc->Read(buffer, size, &ul);
tmp.ReleaseBuffer(ul / sizeof(wchar_t));
*myCStr = CString((LPWSTR)tmp, tmp.GetLength());
// alternatively, you can do the above 2 cases more generically...
typedef CStringT<char or wchar_t> CStreamString;
CStreamString tmp;
buffer = tmp.GetBuffer(size / sizeof(CStreamString::XCHAR));
hrRet = lpSrc->Read(buffer, size, &ul);
tmp.ReleaseBuffer(ul / sizeof(CStreamString::XCHAR));
*myCStr = CString((CStreamString::PXSTR)tmp, tmp.GetLength());
}
}
CATCH_ALL(e)
{
hrRet = STG_E_UNKNOWN;
}
END_CATCH_ALL
_AfxRelease((LPUNKNOWN*)&lpSrc);
return hrRet;
}