【问题标题】:How to determine the buffer size for BufferedOutputStream's write method如何确定 BufferedOutputStream 的 write 方法的缓冲区大小
【发布时间】:2012-04-03 13:19:01
【问题描述】:

我正在尝试使用以下代码复制文件:

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 字节(在 windows 上)。该文件将由用户通过 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() 方法调用。 注意:我已经修剪了我的代码以使其更简单。

【问题讨论】:

  • 如果您正在读取大块数据,则不需要使用缓冲流。他们的目的是将小的读/写变成大块的数据。

标签: java file copy buffer


【解决方案1】:

问题是,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);
}

参考资料:

【讨论】:

  • 我不明白为什么生成的文件比前三个示例中的原始文件小。结果与代码为 while(bufferedInputStream.read(buffer)==buffer.length){ 的结果相同。
  • @boumbh 而这种现象的发生是因为他没有刷新他的 BufferedOutputStream。缓冲区的默认大小为 8192 字节,并在填充时自动刷新。并且最后写入的数据包没有填满流的缓冲区,因此它从未刷新到底层流。此外,在对另一个答案的评论中,艾哈迈德提到他确实有 flush 和 close。但是,我猜他从未刷新/关闭 BufferedOutputStream,而是直接刷新/关闭了底层。因此,缓冲的缓冲区从未得到通知,也从未刷新它的未填充缓冲区。
【解决方案2】:
  1. 为什么文件大小会发生变化?
你忘记了`flush()`(和`close()`): bufferedOutputStream.flush()

您还应该将读取的字节数传递给write 方法:

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

均来自 IO。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 2020-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多