LPSTREAM не может прочитать в CString
Я пытаюсь прочитать текст в CString, используя LPSTREAM, но, похоже, он работает неправильно, вот код, который я вызываю:
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(). Как мне решить эту проблему?
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;
}