在 Java 中如何以原子方式将一个目录替换为另一个目录?
我有一个目录,其中包含为客户端提供的数据文件,例如 /srv/data
。在进行一系列更新时,我正在处理 /srv/data_tmp
,在操作结束时,我想用 data_tmp 自动替换
。当目标是现有目录时,data
File.renameTo()
总是返回 false。我该怎么做?
I have a directory that contains data files served to clients, say, /srv/data
. While making a series of updates, I am working on /srv/data_tmp
, and at the end of the operation, I would like to atomically replace data
with data_tmp
. File.renameTo()
always returns false for me when the destination is an existing directory. How can I do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
恐怕你不能。至少不是SO级别。因此,即使您在 java 应用程序的上下文中管理“原子性”,也无法保证其他“流氓”进程会干扰实际的文件系统级别。
如果我是你,我会阅读这篇文章 (很旧,但应该给你一些想法),然后看看你是否可以将建议的方法移植到 更现代的版本。
哦,等等,已经有人这样做了!
显然您也不是第一个在这里提问的人
祝你好运...
I am afraid you can't. Not at the SO level at least. So even if you manage "atomicity" in the context of your java application, you have no guarantee about some other "rogue" process interfering at the actual filesystem level.
If I were you, I'd read this article (quite old, but should give you some ideas) and then see if you can port the suggested approach to a more modern version .
Oh, wait, someone did this already!
And apparently your aren't the first one to ask here, either
Best of luck...
您可以将
/srv/data
目录替换为符号链接(或 连接在 Windows XP 中),并在适当时更改链接的目标。不过,您无法使用 Java 6 API 来做到这一点 - 您必须依赖库或自己编写命令行命令。
注意:我不保证该操作的原子性。
You could replace the
/srv/data
directory with a symbolic link (or a junction in Windows XP), and change the link's target when appropriate.You won't be able to do that with a Java 6 API though - You'd have to rely on a library or write the command line commands yourself.
NB: I don't guarantee anything about the atomicity of that operation.
Linux
rename
系统调用不允许这样做(rename
系统调用只能覆盖空目录),所以我怀疑在 Linux 上用 Java 可以做到这一点。The Linux
rename
system call doesn't allow this (therename
system call can only overwrite an empty directory), so I doubt it's possible to do in Java on Linux.使用“符号链接”和“重命名”的组合以及中间 tmp 目录完全可以实现此目标。以下示例位于 shell 中,但您可以轻松地将此处的功能转换为使用底层调用:
此处的示例取自:http://axiscorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/
这归结为(在伪代码):
这里的最终重命名是原子的,因此该操作要么成功,要么完全失败,从使用该目录的任何进程来看,该操作都是原子的。
Achieving this goal is entirely possible using a combination of "symlink" and "rename", along with an intermediate tmp directory. The following example is in shell, but you could easily translate the functionality here to use the underlying calls:
Example here taken from: http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/
This boils down to (in pseudo-code):
The final rename here is atomic, so the action will either succeed or fail entirely, from the point of any process using the directory, the action is atomic.