【问题标题】:Clone read bytes of BinaryReader克隆 BinaryReader 的读取字节
【发布时间】:2015-03-24 21:21:27
【问题描述】:

我正在使用 BinaryReader 来解析某些数据。我想将读取的字节复制到辅助流。我该怎么做?

如果我从 BinaryReader 派生(实际上出于不同的原因我需要这样做),我需要覆盖哪些方法才能获得正确的行为?

【问题讨论】:

  • 亲爱的投票者:介意解释一下问题所在吗?这是重复的吗(即使我在搜索中找不到)?
  • 不要派生,封装。创建一个新的流类,并在此流上创建BinaryReader,而您自己的类将自己包装内部流。因此,当BinaryReader 调用Read 时,它将在您的流上,它将从底层流中读取数据,并在同一Read 操作期间将其读取的数据写入另一个流。

标签: c# .net binaryreader


【解决方案1】:

BinaryReader 不是真正的Stream...它更像是另一个流的叠加。你可以:

using (var yourStream = /* ... */)
using (var br = new BinaryReader(yourStream))
{
    using (var ms = new MemoryStream())
    {
        // Important the true, so that the ms remains open!
        using (var bw = new BinaryWriter(ms, Encoding.UTF8, true))
        {
            var readed = br.ReadInt32();
            bw.Write(readed); 
            // All the basic types are supported by various overlaods
        }

        // Here you have your ms... If you want to reread it:
        ms.Position = 0;

        using (var br2 = new BinaryReader(ms, Encoding.UTF8, true))
        {
            // Reread it
        }

        // Or copy it to another stream, or do whatever you want
    }
}

如果您只是想在阅读时在另一个流上复制一个流,您可以使用类似的东西:

public class CopyStream : Stream
{
    // This is the stream you want to read your data from
    public Stream ReadStream { get; set; }

    // This is the "logger" stream, where a copy of read data will be put
    public Stream LogStream { get; set; }

    public override int Read(byte[] buffer, int offset, int count)
    {
        int res = ReadStream.Read(buffer, offset, count);

        if (LogStream != null)
        {
            if (res > 0)
            {
                LogStream.Write(buffer, offset, res);
            }
        }

        return res;
    }

    public override int ReadByte()
    {
        int res = ReadStream.ReadByte();

        if (LogStream != null)
        {
            if (res >= 0)
            {
                LogStream.WriteByte((byte)res);
            }
        }

        return res;
    }

    public override bool CanSeek
    {
        get { return false; }
    }
}

您需要实现/throw NotImplementedException() 很多其他方法,因为Streamabstract class。右击StreamImplement Abstract Class 会加快这个速度。

基本用途是:

var cs = new CopyStream
    {
        ReadStream = yourStream,
        LogStream = whereyouwanttoWriteStream,
    };

using (var br = new BinaryReader(CopyStream, Encoding.UTF8, true))
{
    // Here you can read normally from the BinaryReader.
    // Everything you read will be copied to LogStream 
}

请注意,子类化BinaryReader 相当复杂,因为每个方法加载数据的方式不同,因此没有单一的“拦截点”。

【讨论】:

  • 恐怕这对我不起作用,因为源不可搜索(它是网络流)。
  • 在示例中,MemoryStream 是您复制数据的位置。哪里有 bw.Write 你首先应该有一个 br.Read 从你的流中
  • 确实如此。但我正在使用 many 读取,所以我想自动化克隆数据的过程。
  • 对。这就是我一直在寻找的。但问题是:我需要重写哪些方法?我相当确定我只需要覆盖其中的一些,因为它们在内部被重复使用。但哪些?
  • @mafu 我写的两个ReadDispose(bool disposing),如果你想让你的其他流被自动处理。 Stream.Close 调用Dispose(bool disposing),所以Stream.Close 已经可以了。对于其他一切......不应该写任何东西......然后,如果有,你会得到一个NotImplementedException,你会找到它:-)
【解决方案2】:

流是用来封装的,而不是被覆盖的:

public class DuploStream : Stream
{
    private readonly Stream _underlyingStream;
    private readonly Stream _copyStream;

    public DuploStream(Stream underlyingStream, Stream copyStream)
    {
        _underlyingStream = underlyingStream;
        _copyStream = copyStream;
    }

    public override bool CanRead { get { return true; } }
    public override bool CanSeek { get { return false; } }
    public override bool CanWrite { get { return false; } }

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

    public override long Length { get { throw new NotSupportedException(); } }
    public override long Position { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } }

    public override int Read(byte[] buffer, int offset, int count)
    {
        var bytesRead = _underlyingStream.Read(buffer, offset, count);

        _copyStream.Write(buffer, offset, bytesRead);

        return bytesRead;
    }

    public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
    public override void SetLength(long value) { throw new NotSupportedException(); }
    public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
}

然后,不是在基础流之上创建BinaryReader,而是在DuploStream 之上构建它,传递基础流和复制流。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 1970-01-01
    相关资源
    最近更新 更多