JAVA BufferedOutputStream刷新速度慢,但文件大小正确



我使用BufferedOutputStream写入文件。在调试时,我注意到,即使操作系统显示文件已获得最终大小,刷新操作也需要很长时间。

我的理论:BufferedOutputStream告诉操作系统提前预留空间?所以操作系统已经显示文件与完整的文件大小,即使BufferedOutputStream没有完全刷新?

正确吗?

BufferedOutputStream维护自己的内部byte[]缓冲区。看看代码的实现,它只是在将缓冲区写入底层流之前填充缓冲区。文档没有提供更多的帮助。

如果不考虑每个平台上的本地实现,我认为你不能做出更多的假设。如果你想获得更多的细节,你可以运行strace之类的程序,检查一个简单的程序发生了什么。

我写了下面这个简单的程序
import java.io.*;
public class Test {
    public static void main(String args[]) throws Exception {
        File f = new File("test.txt");
        FileOutputStream fos = new FileOutputStream(f);
        BufferedOutputStream bos = new BufferedOutputStream(fos, 16384);
        for (int i=0;i<10000;++i) {
            bos.write(new byte[1024]);
        }
    }
}

并在其上运行strace。确保使用-f标志来跟踪子进程。下面是运行内容的过滤后的副本。

[pid  6394] mprotect(0x7fdebc03e000, 4096, PROT_READ|PROT_WRITE) = 0
[pid  6394] open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
[pid  6394] fstat(4, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
[pid  6394] mprotect(0x7fdebc03f000, 16384, PROT_READ|PROT_WRITE) = 0
[pid  6394] write(4, ""...,    16384) = 16384
[pid  6394] write(4, ""...,    16384) = 16384
[pid  6394] write(4, ""...,    16384) = 16384

我没有看到任何调用预先预留空间(注意完全确定mprotect,但它似乎不相关)。我在我的Linux机器上看到的行为只是一个缓冲区被填充并写入磁盘。

是否您的文件系统是远程的,因此flush调用通过网络传递数据(另一端的主机可能决定实际"保留"所需的文件空间,并且只在接收到所有字节后才将字节写入磁盘)?还是使用本地文件系统?

检查病毒扫描程序。有时这会减慢文件写入速度。

最新更新