Search code examples
c#azurestreamcompressiongzipstream

How to use one StreamWriter to write to multiple underlying streams?


I am writing text to a System.IO.StreamWriter.

The underlying stream (specified in new StreamWriter(underlyingStream)) writes to a remote file. (I don't think its type is relevant, but for completeness' sake I'll mention it's a microsoft azure CloudBlobStream underlyingStream).

Now, I wanted to extend this by also writing an additional compressed file with the same content, but by using GZipOutputStream compressedUnderlyingStream between the StreamWriter and a second CloudBlobStream.

I was looking for a way to specify both of the CloudBlobStreams as underlying streams of the StreamWriter. But I could not find a way. Does there exist some stream type that can combine two underlying streams? Or how can I otherwise approach this? Note I want everything to stay as streams to minimize amount of data in memory.

//disregard lack of using statements for this example's sake
CloudBlobStream blobStream = blob.OpenWrite();
CloudBlobStream compressedBlobStream = compressedBlob.OpenWrite();
GZipOutputStream compressorStream = new GZipOutputStream(compressedBlobStream);
//I make the streamwriter here for the regular blob,
///but how could I make the same streamwriter also write to the compressedBlob at the same time?
TextWriter streamWriter = new StreamWriter(blobStream, Encoding.UTF8);

Solution

  • I can't think of one off the top of my head, but it would be trivial to write your own:

    class MultiStream : Stream
    {
        private List<Stream> streams;
    
        public Streams(IEnumerable<Stream> streams)
        {
            this.streams = new List<Stream>(streams);
        }
    
        ...
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            foreach(Stream stream in streams)
                stream.Write(buffer, offset, count);
        }
    
        ...
    }
    

    Edit: Thank you to tenbits who has completed the implementation of the above class. Because it is neither my work nor something I have personally tested, I have only provided a link and will leave the original answer unchanged.