2012-04-03 147 views
2

我尝试使用下面的代码复制文件:如何确定缓冲区大小的BufferedOutputStream的write方法

1:

 int data=0; 
     byte[] buffer = new byte[4096]; 
     while((data = bufferedInputStream.read())!=-1){ 
      bufferedOutputStream.write(data); 
     } 

2:

 byte[] buffer = new byte[4096]; 
     while(bufferedInputStream.read(buffer)!=-1){ 
      bufferedOutputStream.write(buffer); 
     } 

实际尺寸文件是3892028字节(在窗口上)。该文件将由用户thro struts2 fileupload上传。上传的文件大小与Windows完全相同。当我尝试从临时文件夹中复制上载的文件时,复制的文件大小不一,所用的时间也会有所不同(可以忽略不计)。请找到下面的读物。

Without using buffer(Code 1) 
Time taken 77 
3892028 
3891200 

Buffer size 1024(Code 2) 
Time taken 17 
3892028 
3891200 

Buffer size 4096(Code 2) 
Time taken 18 
3892028 
3891200 

Buffer size 10240(Code 2) 
Time taken 14 
3892028 
3901440 

Buffer size 102400(Code 2) 
Time taken 9 
3892028 
3993600 

如果我进一步增加缓冲区大小,所花费的时间会增加,同样可以忽略不计。所以我的问题是,

  1. 为什么文件大小改变?
  2. 由于此尺寸变化,是否有任何微妙的后果?
  3. 完成此功能(复制文件)的最佳方法是什么?

我不知道下面会发生什么?感谢您的任何建议。 编辑:我有flush()和close()方法调用。 注:我修剪了我的代码,使其更简单。

+1

如果你正在读大量的数据,你不需要使用缓冲流。它们的目的是将小的读/写转化为大块的数据。 – 2012-04-03 13:43:21

回答

5
  1. 为什么文件大小发生变化?
你忘了`的flush()`(和'close()方法`): bufferedOutputStream.flush()

你也应该通过读取write的字节数方法:

bufferedOutputStream.write(data, 0, bytesRead); 
  1. 完成此功能(复制文件)的最佳方法是什么?

无论从 IO。

+0

我在他们的代码()中有他们。我也会更新我的问题。 – Ahamed 2012-04-03 13:26:19

10

问题是,BufferedInputStream.read(byte[])读取尽可能多的数据到缓冲区中。所以如果流只包含1个字节,只有字节数组的第一个字节会被填充。但是,BufferedInputStream.write(byte[])全部写入流中,这意味着它仍将写入完整的4096个字节,其中包含当前迭代的1个字节和来自先前迭代的4095个剩余字节。

你需要做的是保存读取的字节数量,然后写入相同的数量。

例子:

int lastReadCnt = 0; 
byte[] buffer = new byte[4096]; 
while((lastReadCnt = bufferedInputStream.read(buffer))!=-1){ 
    bufferedOutputStream.write(buffer, 0, lastReadCnt); 
} 

参考文献:

+0

我不明白为什么生成的文件比前三个例子中的原始文件要小。这与代码是'while(bufferedInputStream.read(buffer)== buffer.length){')的结果是一样的。 – boumbh 2015-10-15 16:30:37

+1

@boumbh这种现象发生是因为他没有刷新BufferedOutputStream。缓冲区的默认大小为8192字节,并且每次填充时都会自动刷新。并且写入的最后一批数据没有填充流的缓冲区,因此它从不刷新到基础流。另外,在对另一个答案发表评论时,艾哈迈德提到他确实有'冲水'和'关闭'。但是,我猜他从来没有刷新/关闭BufferedOutputStream,而是直接隐藏底层的。因此缓冲的一个从未被通知,并且永远不会刷新它的未填充的缓冲区。 – bezmax 2015-10-16 07:36:15