【问题标题】:FileChannel#force and bufferingFileChannel#force 和缓冲
【发布时间】:2011-01-20 01:13:57
【问题描述】:

我现在想澄清一下,并在 FileOutputStream 和 FileChannel 之间画出一些相似之处。

首先,使用标准 Java io 编写文件的最有效方法似乎是使用用 BufferedOutputStream 包装的 FileOutputStream。因为它会在内部缓冲区溢出时自动刷新。能够进行单次写入(单字节、浮点数等)以及数组写入很方便,而且不用担心速度。您永远不应该忘记的唯一一件事是关闭它(执行最后一次刷新)。使用 BufferedOutputStream 包装器的好处是显而易见的,并且必须拥有每个人(我希望)。

现在关于 FileChannel。 FileChannel 有force 方法,相当于FileOutputStream 中的flush,不是吗? 而且javadocs 清楚地说,您应该使用它来确保您对目标文件进行了更改。但是,如果没有“BufferedFileChannel”包装器,我不明白何时以及为什么要使用它。 换句话说,FileChannel 的缓冲在哪里?它是否像 BufferedOutputStream 一样自动隐藏在 FileChannel 本身中?如果没有,那我到底为什么需要强制方法,因为没有什么可以强制(使用 write 方法后所有更改都已应用于文件),我必须自己实现缓冲吗?

【问题讨论】:

    标签: java buffering filechannel


    【解决方案1】:

    BufferedOutputStream 有一个缓存在 java 中,而 FileChannel 没有。

    但是,FileChannel 确实具有操作系统级缓存。其中.force()fsync/fdatasync相同。

    在 OpenJDK 6 src/solaris/native/sun/nio/ch/FileChannelImpl.c

      157 JNIEXPORT jint JNICALL
      158 Java_sun_nio_ch_FileChannelImpl_force0(JNIEnv *env, jobject this,
      159                                        jobject fdo, jboolean md)
      160 {
      161     jint fd = fdval(env, fdo);
      162     int result = 0;
      163 
      164     if (md == JNI_FALSE) {
      165         result = fdatasync(fd);
      166     } else {
      167         result = fsync(fd);
      168     }
      169     return handle(env, result, "Force failed");
      170 }
    

    如果您想了解更多操作系统在此级别的工作原理,请阅读this blog

    【讨论】:

    • 所以没有理由在Java级别为FileChannel做额外的缓冲? IE。如果我只使用 64K-256K 的 ByteBuffer 并用所需的信息填充它,直到溢出,然后将其放入 FileChannel#write 会怎样?这个解决方案是使用 FileChannel 的最佳解决方案吗?
    • @Haroogan,(1) 对 FileChannel 的每次写入都是一个系统调用——这涉及一些操作系统级别的开销; (2)java级别的buffer更可预测和可调; (3) 4KB(对齐)块的写入通常会提供最佳性能; (4) 做自己的基准测试
    • FileChannel 没有操作系统级缓存。操作系统会这样做,并且对每个打开的文件都会这样做。或不。与FileChannel 无关。
    猜你喜欢
    • 1970-01-01
    • 2015-07-08
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 2012-10-08
    • 1970-01-01
    • 2013-12-19
    • 2017-09-06
    相关资源
    最近更新 更多