我在NetworkStream之上使用BinaryReader来读取网络上的数据。这对我来说非常有用,但我想了解幕后发生了什么,所以我看了一下BinaryReader的文档,发现它非常稀疏。
我的问题是:当我呼叫BinaryReader.ReadBytes(bufferSize)
时,如果bufferSize
字节在网络流中不存在,ReadBytes
会做什么?
在我看来,有几个选择:
1)读取网络流上存在的任何字节,只返回那么多的字节
2)等到流上出现bufferSize
字节,然后读取
3)抛出异常
我认为选项2正在发生,因为我从未收到过任何例外情况,而且我的所有数据都是全部收到的,而不是分成几部分。但是,我想知道发生了什么。如果有人能够启发我,我将不胜感激。
答案 0 :(得分:10)
我相信实际用于隐藏选项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
并抛出{{ 1}}如果您需要的数据多于关闭之前提供的流。
答案 1 :(得分: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;
}