【问题标题】:How do I flush a 'RandomAccessFile' (java)?如何刷新“RandomAccessFile”(java)?
【发布时间】:2011-11-24 21:32:57
【问题描述】:

我在 java 中使用 RandomAccessFile:

file = new RandomAccessFile(filename, "rw");
...
file.writeBytes(...);

如何确保将这些数据刷新到操作系统?没有 file.flush() 方法。 (请注意,我实际上并不期望它是物理写入的,我对它被刷新到操作系统感到满意,这样数据将在 tomcat 崩溃时幸存下来,但不一定是意外的服务器断电)。

我在 Linux 上使用 tomcat6。

【问题讨论】:

  • 如何将RandomAccessFile 仅刷新到操作系统而不一定要刷新到物理磁盘?
  • 数据被写入磁盘缓存页面,因此其他进程立即可见,并且在写入数据但未写入磁盘的进程崩溃时也会幸免于难,因此会无法生存,例如突然断电。

标签: java flush


【解决方案1】:

我带着同样的好奇心来到这里。

我真的不知道需要在操作系统上刷新而不一定需要刷新到磁盘部分是什么意思。

在我看来,

正如@AVD 所说,与托管刷新 概念最匹配的是getFD().sync()

try(RandomAccessFile raw = new RandomAccessFile(file, "rw")) {
    raw.write...
    raw.write...
    raw.getFD().sync();
    raw.wirte...
}

从它的文档看来,它的工作方式与FileChannel#force(boolean)true 所做的工作非常相似。

现在 "rws""rwd" 看起来就像分别指定 StandardOpenOption#SYNCStandardOpenOption#DSYNCFileChannelopen

try(RandomAccessFile raw = new RandomAccessFile(file, "rws")) {
    raw.write...
    raw.write...
    raw.wirte...
    // don't worry be happy, woo~ hoo~ hoo~
}

【讨论】:

    【解决方案2】:

    这是我在我的应用中所做的:

    rf.close();
    rf = new RandomAccessFile("mydata", "rw");
    

    这可以提高 3-4 倍的性能 与 getFd().sync() 相比,与 "rws' 模式相比 5-7 倍

    deo 完全符合原始问题的建议:通过 将未保存的数据保存到操作系统和 JVM 之外。身体上没有 写入磁盘,因此不会引入烦人的延迟

    【讨论】:

    • 如果你只是删除这两行,什么都不会改变,除了 Java 需要更少的垃圾收集并且文件系统缓存可能会变得更有效率。
    【解决方案3】:

    仔细看看 RandomAccessFile 的构造函数 javadoc:

    “rws”和“rwd”模式的工作方式很像 FileChannel 类的 force(boolean) 方法,分别传递 true 和 false 参数,只是它们总是适用于每个 I/O 操作,因此通常更高效。如果文件驻留在本地存储设备上,那么当调用此类方法返回时保证该调用对文件所做的所有更改都将写入该设备。这对于确保在系统崩溃时不会丢失关键信息很有用。如果文件不在本地设备上,则不会做出此类保证。

    【讨论】:

    • 恕我直言,您的意思是什么?你的意思是任何人都应该使用rwsrwd 来保证vflushingv?那么rw 是干什么用的?
    • @JinKwon Read Write
    【解决方案4】:

    【讨论】:

    • (1) RandomAccessFile 不是 OutputStreamWriter,因此不能用 BufferedAnything 包装。 (2) 真正的目标是停止缓冲,而不是添加它。
    • @cHao - 很酷,非常感谢。那我就回去看书了!
    【解决方案5】:

    提供.flush() 方法的唯一类是那些实际维护自己的缓冲区的类。由于java.io.RandomAccessFile 本身不维护缓冲区,因此不需要刷新。

    【讨论】:

    • Jim Yingst 说:“我应该补充一点,根据我的经验,RandomAccessFile 对于大多数应用程序来说通常很慢。它是一个万事通的类;它可以做很多不同的事情,但是不是特别擅长其中任何一个。您通常可以创建一个流组合,以更高的效率完成您想要的操作。"
    • @TimCooper 您的评论是针对 OP,而不是这个答案,对吧?
    【解决方案6】:

    你可以使用getFD().sync()方法。

    【讨论】:

    • 提问者明确表示他们不需要将数据物理写入磁盘,这本质上就是 sync() 方法的用途。
    • @davmac 我宁愿问你也不愿问 OP。 RandomAccessFile 如何只刷新到操作系统而不一定是物理磁盘?
    • @JinKwon 根据 Jonathan Callen 的回答 - 您无需刷新 RandomAccessFile。每次写入时,您写入的数据都会立即传输到操作系统。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多