如果我正在读取的字节还不存在,BinaryReader 会做啥?

Posted

技术标签:

【中文标题】如果我正在读取的字节还不存在,BinaryReader 会做啥?【英文标题】:What does BinaryReader do if the bytes I am reading aren't present yet?如果我正在读取的字节还不存在,BinaryReader 会做什么? 【发布时间】:2012-06-04 08:17:31 【问题描述】:

我在 NetworkStream 之上使用 BinaryReader 从网络中读取数据。这对我来说非常有效,但我想了解幕后发生的事情,所以我查看了 BinaryReader 的文档,发现它非常稀疏。

我的问题是:当我调用ReadBytes 时,如果网络流中没有bufferSize 字节,BinaryReader.ReadBytes(bufferSize) 会做什么?

在我看来,有几个选择: 1) 读取网络流中存在的任何字节并仅返回那么多 2) 等到流中出现bufferSize 字节,然后读取 3) 抛出异常

我假设选项 2 正在发生,因为我从未收到任何异常,并且我的所有数据都是完整接收的,而不是分段接收的。但是,我想确切地知道发生了什么。如果有人能启发我,我将不胜感激。

【问题讨论】:

它将阻止并确保您获得请求的字节数。如果流已关闭并且您已全部阅读,您只会获得更少。 【参考方案1】:

我相信它实际上适用于隐藏选项 4:

在数据可用时读取数据,以与通常手动执行相同的方式循环。如果它在读取时到达流的end,它只会返回一个小于您要求的字节数的值。

这与您的选项 2 略有不同,因为它确实在数据可用时耗尽流 - 它不会等到它可以一次性读取所有数据。

很容易证明,如果它到达末尾,它返回的字节数确实比您要求的要少:

var ms = new MemoryStream(new byte[10]);
var readData = new BinaryReader(ms).ReadBytes(100);
Console.WriteLine(readData.Length); // 10

如果没有自定义流,则更难证明循环部分。需要多次Read调用以返回所有数据。

文档不是很清楚,但返回值部分至少有点有帮助:

一个字节数组,包含从底层流中读取的数据。 如果到达流的末尾,这可能小于请求的字节数。

注意我突出显示的最后一部分,并将其与Stream.Read 进行比较:

读入缓冲区的总字节数。这可能小于请求的字节数如果当前没有那么多字节可用,或者如果已到达流的末尾则为零 (0)。

如果您希望获得准确的数据量并且该数量会有用,我建议您编写一个 ReadExactly 方法,该方法调用 Read 并在需要时抛出 EndOfStreamException比关闭之前提供的流更多的数据。

【讨论】:

感谢您在回复中提供的详细信息。不过,我确实有一个快速、简单的问题。只有在流关闭时才能到达流的末尾,对吗?【参考方案2】:

如果,通过“出现在流上”,您是在询问该方法是否会阻塞,直到指定的字节数可用,那么它是选项 2。如果 已到达流的结尾

下面是一些关于如何实现BinaryReader.ReadBytes(int) 的示例代码:

byte[] ReadBytes(int count)

    byte[] buffer = new byte[count];
    int total = 0;
    int read = 0;

    do
    
        read = stream.Read(buffer, read, count - total);
        total += read;
    
    while (read > 0 && total < count);

    // Resize buffer if smaller than count (code not shown).

    return buffer;

【讨论】:

以上是关于如果我正在读取的字节还不存在,BinaryReader 会做啥?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 通过 Serial 读取不固定数量的字节

关于处理iis8.0中设置Request.BinaryRead 不允许操作的解决方法

BinaryReader.PeekChar()读取了多少位?

当实体的表还不存在时,实体框架的行为是啥?

读取 JPG 文件,直到出现某些字节

libevent:从缓冲区读取所有字节