Search code examples
c#.netbinaryreader

Clone read bytes of BinaryReader


I'm using a BinaryReader to parse certain data. I would like to copy the read bytes to a secondary stream. How can I do that?

If I derive from BinaryReader (I need to do that for a different reason anyway, actually), which methods do I need to overwrite for correct behavior?


Solution

  • BinaryReader isn't a real Stream... It is more an overlay on another stream. You could:

    using (var yourStream = /* ... */)
    using (var br = new BinaryReader(yourStream))
    {
        using (var ms = new MemoryStream())
        {
            // Important the true, so that the ms remains open!
            using (var bw = new BinaryWriter(ms, Encoding.UTF8, true))
            {
                var readed = br.ReadInt32();
                bw.Write(readed); 
                // All the basic types are supported by various overlaods
            }
    
            // Here you have your ms... If you want to reread it:
            ms.Position = 0;
    
            using (var br2 = new BinaryReader(ms, Encoding.UTF8, true))
            {
                // Reread it
            }
    
            // Or copy it to another stream, or do whatever you want
        }
    }
    

    If you simply want to duplicate a stream on another stream while you are reading it, you can use something like:

    public class CopyStream : Stream
    {
        // This is the stream you want to read your data from
        public Stream ReadStream { get; set; }
    
        // This is the "logger" stream, where a copy of read data will be put
        public Stream LogStream { get; set; }
    
        public override int Read(byte[] buffer, int offset, int count)
        {
            int res = ReadStream.Read(buffer, offset, count);
    
            if (LogStream != null)
            {
                if (res > 0)
                {
                    LogStream.Write(buffer, offset, res);
                }
            }
    
            return res;
        }
    
        public override int ReadByte()
        {
            int res = ReadStream.ReadByte();
    
            if (LogStream != null)
            {
                if (res >= 0)
                {
                    LogStream.WriteByte((byte)res);
                }
            }
    
            return res;
        }
    
        public override bool CanSeek
        {
            get { return false; }
        }
    }
    

    You'll need to implement/throw NotImplementedException() many other methods, because Stream is an abstract class. Right click on the Stream, Implement Abstract Class will speedup this.

    The basic use is:

    var cs = new CopyStream
        {
            ReadStream = yourStream,
            LogStream = whereyouwanttoWriteStream,
        };
    
    using (var br = new BinaryReader(CopyStream, Encoding.UTF8, true))
    {
        // Here you can read normally from the BinaryReader.
        // Everything you read will be copied to LogStream 
    }
    

    Note that subclassing BinaryReader is quite complex, because each method loads the data in a different way, so there isn't a single "point of interception".