9

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

我的问题是:如果我打电话时网络流上不存在字节怎么BinaryReader.ReadBytes(bufferSize)办?bufferSizeReadBytes

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

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

4

2 回答 2

12

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

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

这与您的选项 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

于 2012-05-30T05:49:08.877 回答
0

如果通过“出现在流上”,您询问该方法是否会阻塞,直到指定的字节数可用,那么它是选项 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;
}
于 2012-05-30T05:40:22.323 回答