Igor Pashchuk
Igor Pashchuk

Reputation: 2491

How to determine how much data have been read by XmlTextReader?

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
    }
  }
}

Upvotes: 2

Views: 314

Answers (1)

Igor Pashchuk
Igor Pashchuk

Reputation: 2491

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);
        }
    }
}

Upvotes: 3

Related Questions