Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File Clojure中的原子文件替换_File_Clojure_Atomic - Fatal编程技术网

File Clojure中的原子文件替换

File Clojure中的原子文件替换,file,clojure,atomic,File,Clojure,Atomic,我有一个应用程序可以写入更新磁盘文件,但我希望尽可能确保文件的早期版本不会损坏 当然,更新文件最直接的方法是简单地编写: (spit "myfile.txt" mystring) 然而,如果PC(或java进程)在写入中间死亡,那么文件损坏的可能性就很小。 更好的解决方案可能是写: (do (spit "tempfile" mystring) (.rename (file "tempfile") "myfile.txt") (delete-file "tempfile"))

我有一个应用程序可以写入更新磁盘文件,但我希望尽可能确保文件的早期版本不会损坏

当然,更新文件最直接的方法是简单地编写:

(spit "myfile.txt" mystring)

然而,如果PC(或java进程)在写入中间死亡,那么文件损坏的可能性就很小。

更好的解决方案可能是写:

(do (spit "tempfile" mystring)
    (.rename (file "tempfile") "myfile.txt")
    (delete-file "tempfile"))
这使用了java文件重命名函数,我认为在大多数情况下,在单个存储设备上执行该函数时通常是原子函数

对Clojure文件IO有更深入了解的Clojure专家对这是否是最好的方法,或者是否有更好的方法在更新磁盘文件时将文件损坏的风险降至最低有什么建议吗


谢谢

你举的例子对我的理解完全是惯用和正确的。我会先删除tempfile,以防上一次运行失败,并添加一些错误检测

这不是Clojure特有的;临时重命名删除方案不能保证POSIX标准下的原子替换。这是由于写入重新排序的可能性-重命名可能会在临时写入之前到达物理磁盘,因此,在此时间窗口内发生电源故障时,会发生数据丢失。这不是一种纯粹的理论可能性:


写入临时文件后,需要一个fsync()。讨论从Java调用fsync()。

根据您的评论反馈,我建议您避免尝试运行自己的文件备份数据库,这是基于以下几点观察:

  • 数据结构在文件系统中的持久存储在崩溃时保持一致是一个很难解决的问题。很多非常聪明的人花了很多时间思考这个问题
  • 随着时间的推移,小型数据库往往会发展成大型数据库并收集额外的功能。如果你自己动手,你会发现自己在整个项目过程中都在重新发明轮子

如果您真的对在发生崩溃时保持应用程序数据的一致性感兴趣,那么我建议您考虑嵌入许多可用的免费数据库中的一个-您可以从Berkely DB、HyperSQL或更具Clojure风格的数据库开始,Datomic。

您是在寻求一种更惯用的方法来执行相同的tempfile rename delete path,还是一种更可靠的方法来保持文件结构的一致性?当问题解决时,我正在寻找保持文件结构一致性的最佳方法(我正在为一个项目构建一个基于文件的小数据库,并希望确保我正确地执行了文件io。)为什么要删除tempfile?假设
.rename
等同于
mv
源文件应该不再存在。这不应该是
rename to
?我看不到
rename()
java.io.File
中的
。谢谢。这看起来正是我需要知道的。让我等待更多反馈,然后将您的答案标记为“正确”谢谢Arthur,这真的很有帮助。不过,Rafal的回答类似,但更复杂,在技术细节上略胜一筹。嗨,Alex:我认为你在几乎所有情况下都是绝对正确的。不过,我认为我有一个罕见的外部数据库不实用的用例。(我不知道这个问题答案的部分原因正是因为我通常使用您推荐的外部DB…)谢谢你的回答!这就是我推荐嵌入式数据库的原因。例如,Berkely DB和HSQLDB都可以提供对文件备份数据库的进程内访问,而无需与外部进程通信。有趣的是……你是对的,这可能是我需要使用的。