4

我最近看到了这个网页http://www.yoda.arachsys.com/csharp/readbinary.html ,它解释了从文件流中读取时要采取的预防措施。它的要点是以下代码并不总是有效:

// Bad code! Do not use!
FileStream fs = File.OpenRead(filename);
byte[] data = new byte[fs.Length];
fs.Read (data, 0, data.Length);

这是危险的,因为 Read 的第三个参数是要读取的最大字节数,您应该使用 Read 的返回值来检查实际读取了多少。

我的问题是,在从内存流中读取数据时,您是否应该采取同样的预防措施?在哪些情况下 Read 可能会在读取所有字节之前返回?

4

4 回答 4

7

好吧,我相信如果可以的话,当前的实现MemoryStream总是会填满缓冲区——除非你有一些从它派生的邪恶类。但据我所知,这并不能保证。该文档甚至包含警告:

即使没有到达流的末尾,实现也可以自由地返回比请求更少的字节。

就个人而言,除非它使事情变得更容易,否则我总是会防御性地编写此代码。你永远不知道什么时候有人会改变流的类型,而不会注意到发生了什么。

通常情况下MemoryStream,我想要一次所有字节:所以我调用MemoryStream.ToArray. 这保证可以工作,如果有人将代码更改为不使用 a MemoryStream,它将无法编译为该成员的 only on MemoryStream。对于一般流,我使用一种实用方法,它从流中完全读取并返回一个字节数组。

于 2009-09-18T15:13:46.270 回答
1

我想不出任何正常的理由MemoryStream。非托管可能是另一回事。

无论如何,该命令总是很方便。:)GetBuffer() ToArray()

于 2009-09-18T15:15:27.860 回答
0

是的,您应该始终知道在调用Read. 路由原因可能因流类型而异,但本质上,当您尝试读取超出流末尾的内容时,返回值将小于实际缓冲区大小。

于 2009-09-18T15:15:01.340 回答
0

这是MSDN所说的:

...如果该字节数当前不可用,则可以小于请求的字节数,或者如果在读取任何字节之前到达流的末尾,则为零。

即使没有到达流的末尾,实现也可以自由地返回比请求更少的字节。

请注意术语“实现......”。

于 2009-09-18T15:16:48.760 回答