还有更给它不仅仅是“的文件可能不适合在内存”。为Stream.Read
合同明确说:
这种方法的
实现从 电流流读取 最大的数个字节,并将它们存储在缓冲区 开始偏移量。 流内的当前位置是 先读取的字节数;然而,如果发生异常,流 内的当前位置保持不变。实现 返回读取的字节数。仅当 位置当前位于 流的末尾时, 返回值为零。在 没有数据可用的情况下,该实现将 阻塞,直到可以读取至少一个字节的数据 。仅当 流 中没有更多数据且预期不再有更多数据(例如 关闭的套接字或文件结尾)时,只读取返回0。即使未到达流的结尾 , 实现也可以自由返回比请求少的 字节。
请注意最后一句 - 您不能依靠一个电话来Stream.Read
来读取所有内容。
为FileStream.Read
该文档具有类似的警告:
读入 缓冲区的字节总数。如果 字节当前不是 可用,则可能小于 所请求的字节数,如果达到 流的末尾,则可能为零。
对于本地文件系统,我不确定这是否真的会发生 - 但它可以为网络挂载的文件。你想让你的应用变得脆弱吗?
在一个循环看书做事可靠的方法。我个人更喜欢不要求流支持Length
财产,或者:
public static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[8192];
using (MemoryStream tmpStream = new MemoryStream())
{
int bytesRead;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
{
tmpStream.Write(buffer, 0, bytesRead);
}
return tmpStream.ToArray();
}
}
当长度为事先知道,但它是很好的和简单的稍微低效率的。您只需实施一次,将其放入实用程序库中,并在需要时随时拨打电话。如果您确实介意效率损失,则可以使用CanSeek
来测试Length
属性是否受支持,并在该情况下反复读入单个缓冲区。请注意,尽管在阅读时,流的长度可能会发生变化......
当然,File.ReadAllBytes
会更简单,当您只需处理文件而不是一般流。
有一个很好的理由不承担* *您可以一次性读取它:在'Stream' API并不能保证它会在一个呼叫读到的一切。 – 2009-12-29 12:20:27
'buffer'显式设置为文件的长度。所以你的第一段没有真正回答这个问题。 – 2009-12-29 12:23:22