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 будет работать правильно только если:

  1. поток содержит символы ANSI и TCHAR карты для char,

  2. поток содержит символы 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;
}
Другие вопросы по тегам