如何判断XmlTextReader读取了多少数据?

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

当我处理 XML 时,我如何确定我已经处理了多少数据,是字节还是字符?如果底层流是 FileStream,那将很容易。我怎样才能用底层 NetworkStream?

性能和内存方面的考虑非常重要。

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

按照@AlexeiLevenkov 的建议,我为我的用例实现了一个简单的流包装器。

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