【问题标题】:How to determine how much data have been read by XmlTextReader?如何确定 XmlTextReader 读取了多少数据?
【发布时间】:2015-07-28 21:07:04
【问题描述】:

在处理 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
    }
  }
}

【问题讨论】:

  • 将流包装成另一个并计数?
  • Read():从流中读取下一个节点。
  • 谢谢,@AlexeiLevenkov
  • 它与您的用例没有直接关系(除非您知道您的输入是线性化的!)但值得注意的是 XmlTextReader 实现了 IXmlLineInfo msdn.microsoft.com/en-us/library/… 这可以让您获得当前位置采用 Line / Char (on line) 格式,这可能对未来搜索此问题的人有用。
  • 谢谢,@tolanj。我曾考虑过这种方法,但意识到由于每行的长度不统一,因此在跟踪大小方面需要大量开销。

标签: c# .net networkstream xmltextreader


【解决方案1】:

按照@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);
        }
    }
}

【讨论】:

  • 如果性能是一个问题,您应该考虑覆盖 all Stream 的虚拟方法以调用底层实例的相同方法。例如,许多流提供的实现具有优于默认 ReadByte 实现的性能增强。
猜你喜欢
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 2012-10-07
  • 2013-05-14
  • 2020-05-29
  • 1970-01-01
相关资源
最近更新 更多