c# - 为什么我需要一段一段地读取文件来缓冲?

标签 c# file io

我看到了以下用于将文件放入数组的代码,该数组又用作 SQL 命令的参数,将其插入到 blob 列中:

using (FileStream fs = new FileStream(soubor,FileMode.Open,FileAccess.Read))

int length = (int)fs.Length;
buffer = new byte[length];
int count;
int sum = 0;
while ((count = fs.Read(buffer, sum, length - sum)) > 0)
    sum += count;

为什么我不能简单地这样做:

fs.Read(buffer, 0, length) 只是为了将文件内容复制到缓冲区?

谢谢

最佳答案

它不仅仅是“文件可能不适合内存”。契约(Contract)为Stream.Read 明确地说:

Implementations of this method read a maximum of count bytes from the current stream and store them in buffer beginning at offset. The current position within the stream is advanced by the number of bytes read; however, if an exception occurs, the current position within the stream remains unchanged. Implementations return the number of bytes read. The return value is zero only if the position is currently at the end of the stream. The implementation will block until at least one byte of data can be read, in the event that no data is available. Read returns 0 only when there is no more data in the stream and no more is expected (such as a closed socket or end of file). An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached.

请注意最后一句话 - 您不能依赖对 Stream.Read 的一次调用来阅读所有内容。

FileStream.Read 的文档有类似的警告:

The total number of bytes read into the buffer. This might be less than the number of bytes requested if that number of bytes are not currently available, or zero if the end of the stream is reached.

对于本地文件系统,我不确定这是否真的会发生——但它可以用于网络安装的文件。您希望您的应用以这种方式变得脆弱吗?

循环读取是做事的稳健方式。我个人更喜欢不要求流支持 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 会更简单地实现这一目的。

关于c# - 为什么我需要一段一段地读取文件来缓冲?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1974200/

相关文章:

c# - 有没有办法使用部分填充的对象搜索 List<T>?

c# - 尝试使用 C# ftpwebrequest 将 xml 文件 ftp 到 Zebra 打印机时出错

c# - 如何查询这种结构的xml?

c - 使用通配符操作输入 .txt

Linux 文件描述符 - 获取当前重定向标准输出文件?

c# - 传入枚举作为方法参数

python - 从用户那里获取输入,然后根据他们所说的命名一个 .txt 和一个 .csv 文件

c++ - 在C++中打开二进制文件,更改打开文件的模式

bash ->& 是什么意思?

Java 文件到二进制的转换