2014-09-29 196 views
2

我正在尝试从InputStream中读取。我写下面的代码如何决定从输入流中读取多少个字节?

byte[] bytes = new byte[1024 * 32]; 
       while (bufferedInStream.read(bytes) != -1) { 
        bufferedOutStream.write(bytes); 
       } 

我不明白的是我应该读一遍迭代多少字节?该流包含保存在磁盘上的文件。

我读here但我真的不明白这个帖子。

+0

据我所知,你引用的文章说如果你从磁盘读取,你可以使用从8 KB到64 KB。如果您的文件大小小于64 KB,则可以通过一次迭代或最多两次读取它。 – GokcenG 2014-09-29 08:58:35

+0

使用缓冲区的原因是它比一次读取一个字节更快。这是一个有效的缓冲区大小,取决于您要复制的内容,即它是套接字或文件还是USB。 512字节和64 KB之间的大小往往是有效的。例如大于1 MB的大小可能会比较小的缓冲区慢。 – 2014-09-29 13:28:39

回答

2

假设您有水从管道流入洗澡。然后,你用一个水桶从浴缸里取水,然后带着说你的花园给草坪浇水。浴是缓冲区。当你在草坪上行走时,缓冲器已经填满了,所以当你回来的时候,有一个桶可供你再次使用。

如果浴缸很小,那么当你用水桶行走时它会溢出,所以你会失水。如果你有一个巨大的沐浴,那么它不可能溢出。所以更大的缓冲区更方便。但当然一个更大的浴缸需要更多的钱并占用更多的空间。

程序中的缓冲区占用内存空间。你不想为你的缓冲区占用所有可用的内存,只是因为它很方便。

通常在读取功能中,您可以指定要读取的字节数。所以,即使你有一个小的缓冲区,你可以做到这一点(伪):

const int bufsize = 50; 
buf[bufsize]; 
unsigned read; 
while ((read = is.read(buf, bufsize)) != NULL) { 
    // do something with data - up to read bytes 
} 

在上面的代码中bufzise是读入缓冲区最大数据。

如果您的读取函数不允许您指定要读取的最大字节数,那么您需要提供足够大的缓冲区以获得尽可能大的读取量。

所以最佳缓冲区大小是特定于应用程序的。只有应用程序开发人员会知道数据的特征。例如,水流入浴池的速度有多快。你能买得起什么浴缸尺寸(嵌入式应用程序),你可以多快地从花园里洗澡,然后再回来。

+1

当读取文件的结尾或从套接字读取时,读取的大小大部分时间都不匹配缓冲区。即你不能忽视它。 – 2014-09-29 13:26:23

+1

@PeterLawrey真的,我没有太严格的伪代码,我加了一个读数 - 这可能是有益的。 – 2014-09-29 14:06:30

0

基本上,你有你指定(1024 * 32)

然后长度的字节容器,InputStream的会,直到它到达的填充的结束尽可能,可能是全容器,迭代整个迭代文件时,它将会只填写剩余的字节,并返回-1下一个循环(一个它不能读取任何东西)

所以你基本上是从输入复制粘贴&输出1024 * 32字节大小的块

希望它能帮助你理解代码

顺便说一句,最后一次迭代,如果输入流少于1024 * 32,输出将不仅接收文件的最后部分,而且还会重复先前的迭代内容最后一次迭代。

0

这个想法并不是一次使用缓冲输入流来读取整个文件内容。您使用缓冲输入流来读取与bytes []数组大小相同数量的字节。您使用读取的字节,然后继续读取文件中的更多字节。因此,您不需要知道文件大小就可以读取它。

这篇文章会更有帮助,因为它解释了为什么你应该换一个FileInputStream一个缓冲的输入流

Why is using BufferedInputStream to read a file byte by byte faster than using FileInputStream?

4

这取决于可用内存,文件大小和其他东西。你最好做一些测量。

PS:你的代码是错误的。 bufferedInStream.read(bytes)可能无法填满所有缓冲区?但只是其中的一部分。该方法返回实际的字节数作为结果。

byte[] bytes = new byte[1024 * 32]; 
int size; 
while ((size = bufferedInStream.read(bytes)) != -1) { 
    bufferedOutStream.write(bytes, 0, size); 
}