我有一个目录,其中包含提供给客户的数据文件,例如/srv/data
。在进行一系列更新时,我正在处理/srv/data_tmp
,并且在操作结束时,我希望用data
原子地替换data_tmp
。当目标是现有目录时,File.renameTo()
总是为我返回false。我怎么能这样做?
答案 0 :(得分:1)
您可以使用符号链接(或junction in Windows XP)替换/srv/data
目录,并在适当时更改链接的目标。
但是,您无法使用Java 6 API执行此操作 - 您必须依赖库或自行编写命令行命令。
注意:我不保证该操作的原子性。
答案 1 :(得分:1)
Linux rename
系统调用不允许这样做(rename
系统调用只能覆盖一个空目录),所以我怀疑在Linux上用Java做这件事。
答案 2 :(得分:1)
恐怕你做不到。至少不在SO级别。因此,即使您在Java应用程序的上下文中管理“原子性”,也无法保证其他一些“流氓”进程会干扰实际的文件系统级别。
如果我是你,我会阅读this article(相当陈旧,但应该给你一些想法),然后看看你是否可以将建议的方法移植到more modern version。
哦,等等,有人已经this了!
显然你不是the first one to ask here,也不是
祝您好运......
答案 3 :(得分:0)
使用"符号链接"的组合完全可以实现这一目标。和"重命名",以及一个中间的tmp目录。以下示例在shell中,但您可以轻松地在此处转换功能以使用基础调用:
mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./
此处的示例来自:http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/
这归结为(伪代码):
mkdir('./tmp');
mkdir('./tmp/real_dir1');
mkdir('./tmp/real_dir2');
symlink('./tmp/real_dir1', './target_dir')
symlink('./tmp/real_dir2', './tmp/target_dir')
rename('./tmp/target_dir', './target_dir')
此处的最终重命名是原子的,因此操作将成功或完全失败,从使用该目录的任何进程来看,该操作都是原子的。