2

As I'm processing the XML, how can I determine how much data I have already processed, whether in bytes or in characters? If the underlying stream were a FileStream, it would be easy. How can I do it with an underlying NetworkStream?

Performance and memory considerations are very important.

NetworkStream reportStream = GetStream();
using (var bufferStream = new BufferedStream(reportStream))
{
  using (var xmlTextReader = new XmlTextReader(bufferStream))
  {
    while (xmlTextReader.Read())
    {
      // TODO check how much data have been read already
      // bufferStream.Position and bufferStream.Length don't work 
      // because NetworkStream doesn't support them by design

      // process XML data
    }
  }
}
Igor Pashchuk
  • 2,455
  • 2
  • 22
  • 29
  • 1
    Wrap the stream into another and count? – Alexei Levenkov Jul 27 '15 at 18:31
  • `Read()`: Reads the next node from the stream. – Daniel A. White Jul 27 '15 at 18:31
  • Thanks, @AlexeiLevenkov – Igor Pashchuk Jul 27 '15 at 20:17
  • Its not directly relevant for your use case (unless you _know_ your input is linarized!) but worth noting that XmlTextReader implements IXmlLineInfo https://msdn.microsoft.com/en-us/library/system.xml.ixmllineinfo(v=vs.110).aspx which can get you your current position in Line / Char (_on line_) format which may be useful for future searchers of this question. – tolanj Jul 28 '15 at 13:24
  • thanks, @tolanj. I had considered the approach but realized that it would require significant overhead in keeping track of the size given that the length of each line is not uniform. – Igor Pashchuk Jul 28 '15 at 14:26

1 Answers1

3

As suggested by @AlexeiLevenkov, I implemented a simple stream wrapper for my use case.

public class CountingStream : Stream
{
    private Stream _stream;
    private long _totalBytesRead;
    private long _totalBytesWritten;

    public CountingStream(Stream stream)
    {
        _stream = stream;
        _totalBytesRead = 0;
        _totalBytesWritten = 0;
    }

    public long TotalBytesRead { get { return _totalBytesRead; } }
    public long TotalBytesWritten { get { return _totalBytesWritten; } }

    public override void Flush()
    {
        _stream.Flush();
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        return _stream.Seek(offset, origin);
    }

    public override void SetLength(long value)
    {
        _stream.SetLength(value);
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int bytesRead = _stream.Read(buffer, offset, count);
        _totalBytesRead += bytesRead;
        return bytesRead;
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        _totalBytesWritten += count;
        _stream.Write(buffer, offset, count);
    }

    public override bool CanRead
    {
        get { return _stream.CanRead; }
    }

    public override bool CanSeek
    {
        get { return _stream.CanSeek; }
    }

    public override bool CanWrite
    {
        get { return _stream.CanWrite; }
    }

    public override long Length
    {
        get { return _stream.Length; }
    }

    public override long Position
    {
        get { return _stream.Position; }
        set { _stream.Position = value; }
    }

    protected override void Dispose(bool disposing)
    {
        try
        {
            if (!disposing)
                return;
            if (_stream == null)
                return;

            try
            {
                Flush();
            }
            finally
            {
                _stream.Close();
            }
        }
        finally
        {
            _stream = null;
            base.Dispose(disposing);
        }
    }
}
Igor Pashchuk
  • 2,455
  • 2
  • 22
  • 29
  • 2
    If performance is a concern, you should consider overriding *all* the virtual methods of `Stream` to call to the same methods of the underlying instance. Many streams provide implementations with performance enhancements that are superior to the default `ReadByte` implementation, for example. – Paul Turner Jul 28 '15 at 13:17