LPSTREAM将整个Stream内容读入unsigned char *数组

时间:2018-02-03 01:34:42

标签: c file winapi stream ole

我在复合存储中有一个流。我想将其数据读入字节数组。我对我需要放入lpSrc-> Read()的第二个参数感到困惑。我想将ENTIRE文件读入我的unsigned char *(byte *)数组:

        unsigned char* rawData;
        LPSTREAM lpSrc = NULL;
        HRESULT hrRet = STG_E_INVALIDPARAMETER;

        TRY
        { 
            USES_CONVERSION;
            HRESULT hrSrc = pStg->GetStg()->OpenStream(CT2COLE(szStream),
            NULL,
            STGM_READ | STGM_SHARE_EXCLUSIVE,
            0,
            &lpSrc);

            if (hrSrc != NOERROR)
            {
                hrRet = hrSrc;
            }
            else
            {               
                ULONG ul;
                hrRet = lpSrc->Read(rawData, /*???*/, &ul);             
            }

        }
        CATCH_ALL(e)
        {
            hrRet = STG_E_UNKNOWN;
        }
        END_CATCH_ALL

我在阅读流时尝试了很多变化,所以我不能完全确定这是我应该首先采用的方式。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

  

我对我需要放入lpSrc-> Read()的第二个参数感到困惑。

答案在文档中:

ISequentialStream::Read method

  

pv [out]

     

指向读取流数据的缓冲区的指针。

     

cb [in]

     

要从流对象读取的数据的字节数

     

pcbRead [out]

     

指向ULONG变量的指针,该变量接收从流对象读取的实际字节数。

您必须指定要从流中读取到缓冲区中的字节数。

  

我想将ENTIRE文件读入我的unsigned char *(byte *)数组:

这意味着您必须首先知道流中有多少字节可用。你可以从IStream::Stat()方法得到它。然后,您必须将rawData缓冲区分配给该大小,然后才能将数据读入缓冲区。

尝试这样的事情:

#ifndef SIZE_MAX
#define SIZE_MAX ((size_t)(-1))
#endif

unsigned char* rawData;
LPSTREAM lpSrc = NULL;
HRESULT hrRet = STG_E_INVALIDPARAMETER;

TRY
{ 
    USES_CONVERSION;
    hrRet = pStg->GetStg()->OpenStream(
        CT2COLE(szStream),
        NULL,
        STGM_READ | STGM_SHARE_EXCLUSIVE,
        0,
        &lpSrc);

    if (hrRet == S_OK)
    {
        STATSTG stat;
        hrRet = lpSrc->Stat(&stat, STATFLAG_NONAME);
        if (hrRet == S_OK)
        {
            if (stat.cbSize.QuadPart > SIZE_MAX)
            {
                hrRet = HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE);
            }
            else
            {
                size_t size = (size_t) stat.cbSize.QuadPart;

                rawData = malloc(size);
                if (!rawData)
                {
                    hrRet = E_OUTOFMEMORY;
                }
                else
                {
                    unsigned char *ptr = rawData;
                    size_t sizeLeft = size;

                    while (sizeLeft != 0)
                    {
                        ULONG ul;
                        hrRet = lpSrc->Read(ptr, (sizeLeft >= MAXDWORD) ? MAXDWORD : (DWORD) sizeLeft, &ul);             
                        if (FAILED(hrRet) || (ul == 0)) break;
                        ptr += ul;
                        sizeLeft -= ul;
                    }

                    if (SUCCEEDED(hrRet))
                    {
                        if (sizeLeft != 0) size -= sizeLeft;
                        // use rawData up to size number of bytes as needed...
                    }

                    free(rawData);
                }
            }
        }

        lpSrc->Release();
    }
}
CATCH_ALL(e)
{
    hrRet = E_UNEXPECTED;
}
END_CATCH_ALL