Search code examples
c#streamdatacontractserializer

Write only stream - get written bytes count with DataContractSerializer


Consider I have the following snippet:

public void Store(Stream s, object t)
{
    var serializer = new DataContractSerializer(target.GetType(),
                                            new DataContractSerializerSettings
                                            {
                                                PreserveObjectReferences = true
                                            });

    serializer.WriteObject(s, target);
}

where s is write-only and doesn't support seeking.

Is there any way to get bytes count that was written to stream by WriteObject? I know I can do it in the following way:

using (var memStream = new MemoryStream())
{
    serializer.WriteObject(serializer, target);
    Debug.WriteLine(memStream.Length);
    memStream.CopyTo(s);
}

but I wonder wheter it is possible to avoid CopyTo - object is quite huge.

EDIT: I've just came up with an idea: I can create a wrapper that counts bytes on write. It's the best solution so fat, but maybe there is another way.

DONE

I've implemented a wrapper: https://github.com/pwasiewicz/counted-stream - maybe it will be useful for someone.

Thanks!


Solution

  • Sample implementation of a wrapper I've made:

    public class CountedStream : Stream
    {
        private readonly Stream stream;
        public CountedStream(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");
    
            this.stream = stream;
        }
    
        public long WrittenBytes { get; private set; }
    
        public override void Flush()
        {
            this.stream.Flush();
        }
    
        public override int Read(byte[] buffer, int offset, int count)
        {
            return this.stream.Read(buffer, offset, count);
        }
    
        public override long Seek(long offset, SeekOrigin origin)
        {
            return this.stream.Seek(offset, origin);
        }
    
        public override void SetLength(long value)
        {
            this.stream.SetLength(value);
        }
    
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (buffer.Length >= offset + count)
                         throw new ArgumentException("Count exceeds buffer size");
            this.stream.Write(buffer, offset, count);
            this.WrittenBytes += count;
        }
    
        public override bool CanRead
        {
            get { return this.stream.CanRead; }
        }
    
        public override bool CanSeek
        {
            get { return this.stream.CanSeek; }
        }
    
        public override bool CanWrite
        {
            get { return this.stream.CanWrite; }
        }
    
        public override long Length
        {
            get { return this.stream.Length; }
        }
    
        public override bool CanTimeout
        {
            get { return this.stream.CanTimeout; }
        }
    
        public override long Position
        {
            get { return this.stream.Position; }
            set { this.stream.Position = value; }
        }
    }