为什么我需要逐个读文件缓冲? [英] Why I need to read file piece by piece to buffer?

查看:121
本文介绍了为什么我需要逐个读文件缓冲?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到了下面的代码来获取文件到数组中,而这又被用作SQL命令插入blob列的参数:

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

为什么我不能简单地做到这一点:

fs.Read(buffer,0,length)以便将文件的内容复制到缓冲区中?

谢谢

解决方案

这不仅仅是文件可能不适合内存。 Stream.Read 明确地说:


这个方法的实现读取一个$
当前流的最大计数字节b $ b,并将它们存储在
缓冲区中,从offset开始。流中的
当前位置是由读取的字节数提高的
;
,但如果发生异常,流
中的
当前位置保持不变。实现
返回读取的字节数。只有当
位置当前位于
流的末尾时,
返回值才为零。在没有数据
可用的情况下,实现将
阻塞,直到至少能够读取一个字节的数据
。只有当
在流
中没有更多的数据,并且没有更多的数据(例如
关闭套接字或文件结束)时,只读返回0。
实现可以自由地返回比所请求的更少的
字节,即使流的最后
还没有到达。


请注意最后一句 - 您不能依靠一次调用 Stream.Read 来读取所有内容。



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


读入
缓冲区的总字节数。如果
字节当前不是
可用,则可能小于
请求的字节数;如果到达
流的末尾,则可能为零。


对于本地文件系统,我不确定这是否真的会发生 - 但它可以为网络挂载的文件。你想让你的应用程序变得脆弱吗?

循环读取是强有力的方法。我个人更喜欢不要求流支持 Length 属性,

 <$ c公共静态字节[] ReadFully(流流)
{
byte [] buffer = new byte [8192];
using(MemoryStream tmpStream = new MemoryStream())
{
int bytesRead; ((bytesRead = stream.Read(buffer,0,buffer.Length))> 0)
{
tmpStream.Write(buffer,0,bytesRead);
}
return tmpStream.ToArray();






当长度事先知道,但它很好,很简单。你只需要实现一次,把它放在一个实用程序库中,并在需要的时候调用它。如果你真的关心效率损失,你可以使用 CanSeek 来测试是否支持 Length 属性,并反复读取在这种情况下,一个单一的缓冲区。请注意,当你阅读的时候,流的长度可能会改变...

当然, File.ReadAllBytes 将会更简单,当你只需要处理一个文件而不是一般的流时就可以实现这个功能。


I have seen following code for getting the file into array, which is in turn used as a parameter for SQL command inserting it into a blob column:

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;

Why I cannot simply do that:

fs.Read(buffer, 0, length) in order to just copy content of file to the buffer?

Thanks

解决方案

There's more to it than just "the file may not fit in memory". The contract for Stream.Read explicitly says:

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.

Note the last sentence - you can't rely on a single call to Stream.Read to read everything.

The docs for FileStream.Read have a similar warning:

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.

For a local file system I don't know for sure whether this will ever actually happen - but it could do for a network mounted file. Do you want your app to brittle in that way?

Reading in a loop is the robust way to do things. Personally I prefer not to require the stream to support the Length property, either:

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();
    }
}

That is slightly less efficient when the length is known beforehand, but it's nice and simple. You only need to implement it once, put it in a utility library, and call it whenever you need to. If you really mind the efficiency loss, you could use CanSeek to test whether the Length property is supported, and repeatedly read into a single buffer in that case. Be aware of the possibility that the length of the stream could change while you're reading though...

Of course, File.ReadAllBytes will do the trick even more simply when you only need to deal with a file rather than a general stream.

这篇关于为什么我需要逐个读文件缓冲?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆