如何通过 C# 将 IStream 存储到文件?

发布于 2024-08-07 19:21:57 字数 782 浏览 2 评论 0原文

我正在使用返回 IStream 对象 (System.Runtime.InteropServices.ComTypes.IStream) 的第 3 方组件。我需要获取该 IStream 中的数据并将其写入文件。我已经成功地完成了这一任务,但我对代码并不满意。

“strm”是我的 IStream,这是我的测试代码...

// access the structure containing statistical info about the stream
System.Runtime.InteropServices.ComTypes.STATSTG stat;
strm.Stat(out stat, 0);
System.IntPtr myPtr = (IntPtr)0;

// get the "cbSize" member from the stat structure
// this is the size (in bytes) of our stream.
int strmSize = (int)stat.cbSize; // *** DANGEROUS *** (long to int cast)
byte[] strmInfo = new byte[strmSize];
strm.Read(strmInfo, strmSize, myPtr);

string outFile = @"c:\test.db3";
File.WriteAllBytes(outFile, strmInfo);

至少,我不喜欢上面评论的 long 到 int 转换,但我想知道是否没有更好的方法来获取原始流长度以上?我对 C# 有点陌生,所以感谢您的指点。

I'm working with a 3rd party component that returns an IStream object (System.Runtime.InteropServices.ComTypes.IStream). I need to take the data in that IStream and write it to a file. I've managed to get that done, but I'm not really happy with the code.

With "strm" being my IStream, here's my test code...

// access the structure containing statistical info about the stream
System.Runtime.InteropServices.ComTypes.STATSTG stat;
strm.Stat(out stat, 0);
System.IntPtr myPtr = (IntPtr)0;

// get the "cbSize" member from the stat structure
// this is the size (in bytes) of our stream.
int strmSize = (int)stat.cbSize; // *** DANGEROUS *** (long to int cast)
byte[] strmInfo = new byte[strmSize];
strm.Read(strmInfo, strmSize, myPtr);

string outFile = @"c:\test.db3";
File.WriteAllBytes(outFile, strmInfo);

At the very least, I don't like the long to int cast as commented above, but I wonder if there's not a better way to get the original stream length than the above? I'm somewhat new to C#, so thanks for any pointers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剩余の解释 2024-08-14 19:21:57

您不需要执行该转换,因为您可以从 IStream 源中分块读取数据。

// ...
System.IntPtr myPtr = (IntPtr)-1;
using (FileStream fs = new FileStream(@"c:\test.db3", FileMode.OpenOrCreate))
{
    byte[] buffer = new byte[8192];
    while (myPtr.ToInt32() > 0)
    {
        strm.Read(buffer, buffer.Length, myPtr);
        fs.Write(buffer, 0, myPtr.ToInt32());
    }
}

这种方式(如果有效)的内存效率更高,因为它只使用一个小内存块在流之间传输数据。

You don't need to do that cast, as you can read data from IStream source in chunks.

// ...
System.IntPtr myPtr = (IntPtr)-1;
using (FileStream fs = new FileStream(@"c:\test.db3", FileMode.OpenOrCreate))
{
    byte[] buffer = new byte[8192];
    while (myPtr.ToInt32() > 0)
    {
        strm.Read(buffer, buffer.Length, myPtr);
        fs.Write(buffer, 0, myPtr.ToInt32());
    }
}

This way (if works) is more memory efficient, as it just uses a small memory block to transfer data between that streams.

寻梦旅人 2024-08-14 19:21:57

System.Runtime.InteropServices.ComTypes.IStream 是 ISequentialStream 的包装器。

来自 MSDN: http://msdn.microsoft.com/ en-us/library/aa380011(VS.85).aspx

实际读取的字节数可以是
小于字节数
如果发生错误或如果
期间到达流的末尾
读操作。数量
返回的字节应该始终是
与字节数相比
要求。如果字节数
返回的数量小于
请求的字节数,通常意味着
Read 方法尝试读取过去
流结束。

该文档说,只要 pcbRead 小于 cb,您就可以循环和读取。

System.Runtime.InteropServices.ComTypes.IStream is a wrapper for ISequentialStream.

From MSDN: http://msdn.microsoft.com/en-us/library/aa380011(VS.85).aspx

The actual number of bytes read can be
less than the number of bytes
requested if an error occurs or if the
end of the stream is reached during
the read operation. The number of
bytes returned should always be
compared to the number of bytes
requested. If the number of bytes
returned is less than the number of
bytes requested, it usually means the
Read method attempted to read past the
end of the stream.

This documentation says, that you can loop and read as long as pcbRead is less then cb.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文