Question

I have a situation in which I am using multiple streams to download a zipped file via http. To do so I need to use multiple streams. I.e. get a web response stream, read into a binary reader stream, write to memory stream using binary writer stream etc etc.

As it's all a bit complicated and nasty I have split everything up into small functions to make it read a bit nicer, but I have a bit of a provlem with the readStreamIntoMemoryStream function which I am calling from the public DownloadCsvReport function, see below:

public IEnumerable<string> DownloadCsvReport(string reportDownloadUrl)
{
    using (Stream responseStream = creatDownloadWebRequest(reportDownloadUrl))
    using (MemoryStream memoryStream = readStreamIntoMemoryStream(responseStream))
    {
        setMemoryStreamToBegining(memoryStream);
        ZipEntry zipEntry = getZippedFileFromMemoryStream(memoryStream);
        return convertZippedFileToCsvRows(zipEntry);
    }
}

private MemoryStream readStreamIntoMemoryStream(Stream webResponseStream)
{
    var memoryStream = new MemoryStream();
    var binaryWriter = new BinaryWriter(memoryStream);
    var binaryReader = new BinaryReader(webResponseStream);

    while (true)
    {
        byte[] buffer = binaryReader.ReadBytes(BufferSize);
        binaryWriter.Write(buffer);

        if (buffer.Length != BufferSize)
        {
            return memoryStream;
        }
    }
}

The thing I am unsure about is whether the BinaryWriter and BinaryReader streams from the private function will be disposed of when the MemoryStream is when the public method loses scope? If not and I wrapped these stream's in using statements within the private method, would it not throw an exception when I tried to access the MemoryStream in the public method?

Was it helpful?

Solution 2

The thing I am unsure about is whether the BinaryWriter and BinaryReader streams from the private function will be disposed of when the MemoryStream is when the public method loses scope?

The thing is, BinaryWriter and BinaryReader are not streams.

They act upon the underlying stream which, in your case, is the memoryStream. So, as long as you close your memoryStream and the outer responseStream, everything is fine.

Edit:

In fact, take a look at their source code:

protected virtual void Dispose(bool disposing)
{
    if (disposing)
        OutStream.Close();
}

As you can see, all it does is call Dispose on the underlying stream. Your current code already does that - so there's no need to dispose of the writer/reader. It would be redundant.

OTHER TIPS

This was a design flaw in the .NET Framework that has been fixed as of .NET 4.5, where you can use overloads of the BinaryWriter and BinaryReader constructors that allow you to leave the stream open after disposing them.

var memoryStream = new MemoryStream();
var encoding = new UTF8Encoding(false, true);
using (var binaryWriter = new BinaryWriter(memoryStream, encoding, true))
using (var binaryReader = new BinaryReader(webResponseStream, encoding, true))
{
    // ...
    return memoryStream;
}

Edit: If you're using .NET 4 (or earlier), you can use the NonClosingStreamWrapper class from Jon Skeet's MiscUtil library:

var memoryStream = new MemoryStream();
using (var memoryStreamWrapper = new NonClosingStreamWrapper(memoryStream))
using (var webResponseStreamWrapper = new NonClosingStreamWrapper(webResponseStream))
using (var binaryWriter = new BinaryWriter(memoryStreamWrapper))
using (var binaryReader = new BinaryReader(webResponseStreamWrapper))
{
    // ...
    return memoryStream;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top