1

TComInterface<IStream> オブジェクトを使用して TMemoryStream に読み込むにはどうすればよいですか? TComInterface<IStream> を TStream* として使用して、TMemoryStream LoadFromStream 呼び出しを使用できますか?

4

1 に答える 1

4

1 つの方法はRead()IStreamデータをバッファに入れ、次にWrite()に移動することですTMemoryStream。たとえば、次のようになります。

TComInterface<IStream> pIStrm;
TMemoryStream *pMStrm;

...

STATSTG stat = {0};
OleCheck(pIStrm->Stat(&stat, STATFLAG_NONAME));

LARGE_INTEGER li;
li.QuadPart = 0;
ULARGE_INTEGER ul;
OleCheck(pIStrm->Seek(li, STREAM_SEEK_CUR, &ul));
unsigned __int64 ulPos = ul.QuadPart;

BYTE buffer[1024];
while (ulPos < stat.cbSize.QuadPart)
{
    ULONG ulRead;
    OleCheck(pIStrm->Read(buffer, min(stat.cbSize.QuadPart - ulPos, sizeof(buffer)), &ulRead));
    pMStrm->WriteBuffer(buffer, ulRead);
    ulPos += ulRead;
}

...

別のオプションは、内部TStreamで にアクセスする 派生クラスを作成することですIStream(RTL のTStreamAdapterクラスが をラップTStreamして として渡せるようにするのと同様IStreamです)。たとえば、次のようになります。

class TIStreamWrapper : public TStream
{
private:
    TComInterface<IStream> pIStrm;

protected:
    virtual __int64 __fastcall GetSize();
    virtual void __fastcall SetSize(const __int64 NewSize);

public:
    __fastcall TIStreamWrapper(IStream *Strm);
    virtual int __fastcall Read(void *Buffer, int Count);
    virtual int __fastcall Write(const void *Buffer, int Count);
    virtual __int64 __fastcall Seek(const __int64 Offset, TSeekOrigin Origin);
};

__fastcall TIStreamWrapper::TIStreamWrapper(IStream *Strm)
    : pIStrm(Strm, true)
{
}

__int64 __fastcall TIStreamWrapper::GetSize()
{
    STATSTG stat = {0};
    OleCheck(pIStrm->Stat(&stat, STATFLAG_NONAME));
    return stat.cbSize.QuadPart;
}

void __fastcall TIStreamWrapper::SetSize(const __int64 NewSize)
{
    ULARGE_INTEGER ul;
    ul.QuadPart = NewSize;
    OleCheck(pIStrm->SetSize(ul));
}

int __fastcall TIStreamWrapper::Read(void *Buffer, int Count)
{
    ULONG ulRead;
    OleCheck(pIStrm->Read(Buffer, Count, &ulRead));
    return ulRead;
}

int __fastcall TIStreamWrapper::Write(const void *Buffer, int Count)
{
    ULONG ulWritten;
    OleCheck(pIStrm->Write(Buffer, Count, &ulWritten));
    return ulWritten;
}

static const DWORD IStreamSeekOrigin[] = {STREAM_SEEK_SET, STREAM_SEEK_CUR, STREAM_SEEK_END};

__int64 __fastcall TIStreamWrapper::Seek(const __int64 Offset, TSeekOrigin Origin)
{
    LARGE_INTEGER li;
    li.QuadPart = Offset;
    ULARGE_INTEGER ul;
    OleCheck(pIStrm->Seek(li, IStreamSeekOrigin[Origin], &ul));
    return ul.QuadPart;
}

TComInterface<IStream> pIStrm;
TMemoryStream *pMStrm;
...
TIStreamWrapper *pWrapper = new TIStreamWrapper(pIStrm);
try
{
    pMStrm->LoadFromStream(pWrapper);
    // or: pMStrm->CopyFrom(pWrapper, 0);
}
__finally
{
    delete pWrapper;
}

...
于 2013-03-15T21:59:27.997 に答える