繁体   English   中英

FileStream.Read()-读取的字节

[英]FileStream.Read() - bytes read

FileStream.Read()返回读取的字节数,但是...除了到达文件末尾之外,是否还有其他情况,它将读取的字节数少于请求的字节数, 并且不会引发异常

该文件说:

Read方法仅在到达流末尾后才返回零。 否则,Read在返回之前总是从流中读取至少一个字节。 如果在调用Read时流中没有可用数据,则该方法将阻塞,直到可以返回至少一个字节的数据为止。 即使未到达流的末尾,实现也可以自由返回少于请求的字节数。

但这并不能完全解释在什么情况下数据将不可用并导致方法阻塞,直到可以再次读取为止。 我的意思是,大多数数据不可用的情况不是应该强制例外吗?

在实际情况下,将读取的字节数与预期的字节数进行比较可能会有所不同(假设当我们提到预期的字节数时,我们已经在检查文件末尾)吗?

编辑:更多信息,我问这个的原因是因为我遇到了一些代码,其中开发人员几乎做了这样的事情:

bytesExpected = (remainingBytesInFile > 94208 ? 94208 : remainingBytesInFile
while (bytesRead < bytesExpected)
{
      bytesRead += fileStream.Read(buffer, bytesRead, bytesExpected - bytesRead)
}

现在,我完全看不到有什么优势,如果它无法读取预期的字节数,我希望它会引发异常(请记住,已经考虑到有很多剩下要读取的字节)

这样的事情可能会有什么原因呢? 我确定我错过了一些东西

该文档适用于Stream.Read ,派生自FileStream 由于FileStream是流,因此它应遵守流协定。 并非所有流都可以,但是除非您有充分的理由,否则应坚持这一点。

在典型的文件流中,到达文件末尾时,返回值只会小于count(这是检查文件末尾的一种非常简单的方法)。

但是,例如,在NetworkStream ,您将一直循环读取,直到该方法返回零-表示流结束。 文件流的工作原理相同-当Read返回零时,您就位于文件末尾。

最重要的是, FileStream不仅适用于您要考虑的文件,还适用于伪文件,例如标准输入/输出管道和COM端口(例如,尝试在PRN上打开文件流)。 在这种情况下,您不会读取固定长度的文件,并且其行为与NetworkStream相同。

最后,不要忘记FileStream没有密封。 例如,对于您来说,实现虚拟文件系统是非常好的-如果您的虚拟文件系统不支持查找或检查文件的长度,那么也非常好。

编辑:

为了解决您的修改,这正是您应阅读任何流的方式。 没错。 如果流中没有其他要读取的内容,则Read方法将仅返回0 ,并且您知道流已结束。 唯一的事情是,似乎他尝试一次将其缓冲区填满,一个缓冲区-仅当您明确需要将文件划分94208字节并将该byte[]传递到某个地方进行进一步处理时,这才有意义。

如果不是这种情况,则实际上不需要填充整个缓冲区-您只需继续读取(可能在另一面进行写入),直到Read返回0 确实,实际上,默认情况下, 除非 FileStream始终围绕管道句柄构建, 否则它将始终填充整个缓冲区-但这是有可能的,因此,只要您需要这些byte[] ,就不应该依赖“真实文件”行为。对于某些非流式的内容(例如,解析消息),这完全可以。 如果仅将流用作实际流,并且将数据流传输到其他位置,则它没有意义,实际上-您只需要while即可读取文件。

您的期望仅适用于流从无延迟源读取数据的情况。 其他I / O源的运行速度可能很慢,这就是为什么Read方法可能无法始终立即返回的原因。 这并不意味着存在错误(因此也不例外),而只是它必须等待数据到达。

例如:网络流,慢速磁盘上的文件流等。

(UPDATE,HDD示例)给出一个特定于文件的示例(由于您的案例是FileStream ,尽管Read是在Stream上定义的,所以所有实现都应满足要求):机械硬盘在不活动时进入“睡眠”状态(特别是在电池供电的设备上,请阅读笔记本电脑)。 旋转可能需要一秒钟左右的时间。 那不是IOException ,但是在读取任何数据之前,您的读取必须等待一秒钟。

简单的答案是,在FileStream上可能永远不会发生。 但是请记住,Read方法是从Stream继承的,Stream是许多其他流(如NetworkStream)的基础,在这种情况下,您可能无法按您的要求读取许多字节,因为它们尚未从网络接收到。

因此,就像文档中所说的那样,这完全取决于特定类型的流的实现-FileStream,NetworkStream等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM