Search code examples
c#.netstream

How do I concatenate two System.IO.Stream instances into one?


Let's imagine I want to stream three files to a user all in a row, but instead of him handing me a Stream object to push bytes down, I have to hand him a Stream object he'll pull bytes from. I'd like to take my three FileStream objects (or even cleverer, an IEnumerable<Stream>) and return a new ConcatenatedStream object that would pull from the source streams on demand.


Solution

  • class ConcatenatedStream : Stream
    {
        Queue<Stream> streams;
    
        public ConcatenatedStream(IEnumerable<Stream> streams)
        {
            this.streams = new Queue<Stream>(streams);
        }
    
        public override bool CanRead
        {
            get { return true; }
        }
    
        public override int Read(byte[] buffer, int offset, int count)
        {
            int totalBytesRead = 0;
    
            while (count > 0 && streams.Count > 0)
            {
                int bytesRead = streams.Peek().Read(buffer, offset, count);
                if (bytesRead == 0)
                {
                    streams.Dequeue().Dispose();
                    continue;
                }
    
                totalBytesRead += bytesRead;
                offset += bytesRead;
                count -= bytesRead;
            }
    
            return totalBytesRead;
        }
    
        public override bool CanSeek
        {
            get { return false; }
        }
    
        public override bool CanWrite
        {
            get { return false; }
        }
    
        public override void Flush()
        {
            throw new NotImplementedException();
        }
    
        public override long Length
        {
            get { throw new NotImplementedException(); }
        }
    
        public override long Position
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    
        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }
    
        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }
    }