Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top