如何确定文件已成功写入? [英] How to be sure a file has been successfully written?

查看:306
本文介绍了如何确定文件已成功写入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将自动保存功能添加到Java中的图形应用程序中。应用程序定期自动保存当前文档,并在退出时自动保存。当用户启动应用程序时,自动保存文件被重新加载。



如果自动保存文件以任何方式损坏(当文件处于中间位置时,被保存会做到这一点?),用户将失去他们的工作。我怎样才能防止这种情况,并尽我所能来保证自动保存文档处于一致的状态?

更复杂的是,为了自动保存文档,我需要保存一个.xml文件和几个.png文件。另外,通过JNI在C代码中发生.png保存。

我现在的策略是写每个.png扩展名为.png.tmp,写入.xml文件扩展名为.xml.tmp,然后重命名每个文件以删除保留.xml的.tmp部分,直到最后。在启动时,我只能加载自动保存文件,如果我能找到一个.xml文件,并忽略.xml.tmp文件。我也不会删除以前的自动保存文档,直到新文档的.xml.tmp文件被重命名为止。



我猜你知道写到磁盘很差。我知道你可以在使用文件的时候有软件读/写缓冲区,以及操作系统和硬件缓冲区,所有这些都需要刷新。我很困惑,如何确切地知道什么时候写了什么东西,以及我能做些什么来保护自己。如果自动保存文件是以任何方式损坏(当文件处于被保存的状态时,我假设断电会这样做),用户将失去工作。如何防止这种情况,并尽我所能来保证自动保存文档处于一致状态?


为了防止丢失由于部分写入自动保存文件的数据,不要覆盖自动保存文件。相反,每次写入一个新文件,然后在安全写入文件之后重新命名。



为防止不知道自动保存文件不正确写:


  1. 注意自动保存文件写入和关闭时抛出的异常,以防盘片错误,文件系统已满等

  2. 保存正在运行的文件校验和,并将其写入文件末尾。然后,当您加载自动保存文件时,请检查校验和是否存在并且是正确的。

如果检查点状态涉及多个文件,确保您按照熟知的顺序编写文件(不会覆盖!),并在安全关闭所有其他文件后,将校验和写入自动保存文件。您可能需要为每个检查点创建一个目录。



后续

没有。我不是说重命名总是成功。但是,原子 - 它要么成功(并且完成),要么文件系统不会更改。所以,如果你这样做:


  1. 写入file.new并关闭,
  2. 删除file,

  3. 将file.new重命名为file

然后提供第一步成功,保证在光盘上安全地保存最新的文件。添加几个步骤很简单,因此您可以随时备份文件。 (如果第三步失败了,你只剩下file.new而没有file,这个可以手动恢复,或者在下一次运行的时候自动被应用程序恢复。)

另外,我并不是说写入总是成功,或者应用程序不会崩溃,或者电源永远不会关闭。校验和的意义在于允许您检测发生这些事情的情况,并且自动保存文件不完整。最后,有两个自动保存是一个好主意,以防您的应用程序陷入数据结构混乱的状态,最后一个自动保存结果是荒谬的。 (校验和将无法防止这种情况发生。)当应用程序崩溃时出于同样的原因,请谨慎自动保存。


I'm adding autosave functionality to a graphics application in Java. The application periodically autosaves the current document and also autosaves on exit. When the user starts the application, the autosave file is reloaded.

If the autosave file is corrupted in any way (I assume a power cut when the file is in the middle of being saved would do this?), the user will lose their work. How can I prevent such situations and do all I can to guarantee that the autosave document is in a consistent state?

To further complicate matters, to autosave the document I need to save one .xml file and several .png files. Also, the .png saving occurs in C code over JNI.

My current strategy is to write each .png with the extension .png.tmp, write the .xml file with the extension .xml.tmp, and then rename each file to remove the .tmp part leaving the .xml until last. On startup, I only load the autosave document if I can find a .xml file and ignore .xml.tmp files. I also don't delete the previous autosave document until the .xml.tmp file for the new document is renamed.

I guess my knowledge of what happens when you write to disk is poor. I know you can have software read/write buffers when using files, as well as OS and hardware buffers and that all of these need to be flushed. I'm confused how I can know for sure when something really has been written to disk and what I can do to protect myself. Does the renaming operation do anything to make sure buffers are flushed?

解决方案

If the autosave file is corrupted in any way (I assume a power cut when the file is in the middle of being saved would do this?), the user will lose their work. How can I prevent such situations and do all I can to guarantee that the autosave document is in a consistent state?

To prevent loss of data due to partially written autosave file, don't overwrite the autosave file. Instead, write to a new file each time, and then rename it once the file has been safely written.

To guard against not noticing that an autosave file has not been correctly written:

  1. Pay attention to the exceptions thrown as the autosave file is written and closed in case a disc error, file system full, etc.
  2. Keep a running checksum of the file as it is written and write it at the end of the file. Then when you load the autosave file, check that the checksum is there and is correct.

If the checkpointed state involves multiple files, make sure that you write the files in a well known order (without overwriting!), and write the checksum on the autosave file after all of the other files have been safely closed. You might want to create a directory for each checkpoint.

FOLLOW UP

No. I'm not saying that rename always succeeds. However, it is atomic - it either succeeds (and completes) or the file system is not changed. So, if you do this:

  1. write "file.new" and close,
  2. delete "file",
  3. rename "file.new" to "file"

then provided the first step succeeds you are guaranteed to have the latest "file" safely on disc. And it is simple to add a couple of steps so that you have a backup of "file" at all times. (If the 3rd step fails, you are left with "file.new" and no "file". This can be recovered manually, or automatically by the application next time you run it.)

Also, I'm not saying that writes always succeed, or that applications don't crash, or that the power never goes off. And the point of the checksum is to allow you to detect the cases where these things have happened and the autosave file is incomplete.

Finally, it is a good idea to have two autosaves in case your application gets itself into a state where its data structures are messed up and the last autosave is nonsensical as a result. (The checksum won't protect against this.) Be cautious about autosaving when the application crashes for the same reason.

这篇关于如何确定文件已成功写入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆