C# 流读取问题

C# 流读取问题,c#,.net,stream,C#,.net,Stream,假设我们有这样一个代码块: //Assuming s is a stream: byte[] data = new byte[1000]; s.Read(data,0,data.Length); //bytesRead will always end up at 1000, unless the stream is itself smaller in length: int bytesRead = 0; int chunkSize = 1; while(bytesRead < data.

假设我们有这样一个代码块:

//Assuming s is a stream:
byte[] data = new byte[1000];
s.Read(data,0,data.Length);
//bytesRead will always end up at 1000, unless the stream is itself smaller in length:
int bytesRead = 0;
int chunkSize = 1;
while(bytesRead < data.Length && chunkSize > 0 )
      bytesRead += chunkSize = s.Read(data,bytesRead,dataLength-bytesRead);
read方法可以在任何地方读取 从1到1000字节,保留 未读流的余额

这就是C#book所说的

我不明白,为什么
Read
方法会读取流中的任何位置?它没有读取所有的流

它说,解决办法应该是这样的:

//Assuming s is a stream:
byte[] data = new byte[1000];
s.Read(data,0,data.Length);
//bytesRead will always end up at 1000, unless the stream is itself smaller in length:
int bytesRead = 0;
int chunkSize = 1;
while(bytesRead < data.Length && chunkSize > 0 )
      bytesRead += chunkSize = s.Read(data,bytesRead,dataLength-bytesRead);
//字节读取总是以1000结尾,除非流本身的长度更小:
int字节读取=0;
int chunkSize=1;
while(bytesRead0)
bytesRead+=chunkSize=s.Read(data,bytesRead,dataLength bytesRead);
本书还提供了上述代码作为解决方法。我试图理解的是,Read方法是否开始读到底,并将指定范围内的所有字节写入字节数组。为什么他使用
bytesRead
作为
s.Read(data,bytesRead,dataLength bytesRead)的起点


提前感谢。

我们的想法是,在您调用Read。。。或者永远。例如,在NetworkStream上,数据到达的速度可能比您拾取数据的速度慢。或者您可能已接近文件流的结尾。流可能知道剩下的字节比您要求的要少,或者它可能无法知道请求的字节何时或是否会全部到达。因此,Read保留返回少于您要求的数据的权利,而不是等待可能永远不会到达的数据,或因“字节不足,请再次猜测”错误而失败


因此,在将块读入字节数组时,可能没有填充字节数组。但您希望将下一个块追加到最后一个块停止的位置,而不是覆盖字节数组的开头。因此,将ByteRead作为将下一个数据块放入字节数组的起始位置。

基于我对Read方法文档的阅读,因为流可用于读取各种数据源,从键盘输入到文件到网络流量,read方法返回的数据是否会返回所请求的字节数,这一点由具体实现决定。例如,如果用于读取网络数据的特定实现希望返回到目前为止可用于web请求的500字节数据,但它希望在读取1000字节之前不会执行此操作,并且您已经请求了1000字节,那么它可能会返回它所拥有的数据,以便您可以对其进行处理。它将告诉您,它只读取500字节,您应该知道,可能还有更多。最大值为1000表示您不希望一次处理超过1000个字节。

第一个示例使用字节数组的声明大小1000作为
读取方法的输入参数

第二个示例是一次读取一个字节的流,这对于流式传输传入或传出数据非常有用——这意味着如果您可以处理正在接收的流的一部分,而不首先将其全部缓冲到内存中,这是一种更有效的方法

我认为您在这里感到困惑的地方是作者人为地将示例限制为最大1000字节。许多涉及流的协议通常在开始时发送一个或两个字节,专门通知消费者流的整体长度,以便它能够最好地对流进行分块和处理,因此不需要声明1000的限制。获得大小,适当地分块(包括可能不是完整的分块大小的最后一个分块),然后处理每个分块

我不明白,为什么要读方法 你会在溪流的任何地方读书吗? 它没有读取所有的流

读取允许您指定读取的起点和终点。更多信息请参见itowlson的答案

我想了解的是 Read方法正在开始读取到 结束并写入中的所有字节 指定的范围到字节数组

如果这是一个问题,我想答案是否定的。Read方法在指定的起点和终点用流中的数据填充数组

为什么他在s.Read(data,bytesRead,dataLength bytesRead)中使用bytesRead作为起点


他使用字节读取来跟踪“读取的字节数”。这让他知道在下一次读取调用时从何处开始读取。

短语“可以读取1到1000字节的任何位置”的意思是“可以读取1字节或2字节,最多1000字节”。它指的是读取的字节长度,而不是位置。读取将位于流的当前位置。

您的意思是,首先他们发送想要发送的数据的大小,然后他们将整个数据作为块发送,而不是作为一个整体发送?通常是的。假设您要传输的磁盘上有一个40 MB的文件。与其在内存中加载40 MB,然后传输它—从而使40 MB的内存在一段时间内变得拥挤—您只需读取,比如说,前1024个字节,然后传输它,并以1024个字节的块继续。文件传输协议可能会声明“第一个数据包的前两个字节包含一个指示有效负载大小的无符号int”,以便您知道何时停止从该流读取。接收端也可以这样做——将其分块成1024字节或其他一些资源友好的缓冲区编号。