为了账号安全,请及时绑定邮箱和手机立即绑定

Windows上可靠的File.renameTo()替代方法?

Windows上可靠的File.renameTo()替代方法?

慕田峪4524236 2019-09-21 11:43:19
File.renameTo()似乎Java 是有问题的,尤其是在Windows上。如API文档所述,此方法的行为的许多方面本质上与平台有关:重命名操作可能无法将文件从一个文件系统移动到另一个文件系统,它可能不是原子的,并且如果具有目标抽象路径名的文件可能无法成功已经存在。应该始终检查返回值,以确保重命名操作成功。就我而言,作为升级过程的一部分,我需要移动(重命名)可能包含千兆字节数据(很多子目录和大小不同的文件)的目录。移动始终在同一分区/驱动器中完成,因此并不需要物理上移动磁盘上的所有文件。这里不应该有任何文件锁定的目录中的内容被移动了,不过,很多时候,renameTo()无法完成其工作,并返回false。(我只是猜测也许某些文件锁在Windows上会任意地到期。)当前,我有一个使用复制和删除的后备方法,但是这种方法很麻烦,因为它可能要花费很多时间,具体取决于文件夹的大小。我也在考虑简单地记录一个事实,即用户可以手动移动文件夹,以免潜在地等待数小时。但是正确的方法显然是自动而快速的。所以我的问题是,您是否知道另一种可靠的方法,可以在Windows上使用Java(使用普通的JDK或某些外部库)进行快速移动/重命名。或者,如果您知道一种检测和释放给定文件夹及其所有内容(可能是成千上万个单独文件)的任何文件锁的简便方法,那也可以。
查看完整描述

3 回答

?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

另请参见Files.move()JDK 7中的方法。


一个例子:


String fileName = "MyFile.txt";


try {

    Files.move(new File(fileName).toPath(), new File(fileName).toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);

} catch (IOException ex) {

    Logger.getLogger(SomeClass.class.getName()).log(Level.SEVERE, null, ex);

}


查看完整回答
反对 回复 2019-09-21
?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

对于它的价值,还有一些其他概念:

  1. 在Windows上,renameTo()即使目标目录存在,即使它为空,似乎也会失败。就像我在Linux上尝试过的renameTo()那样,只要目标为空,只要目标存在,它就会成功,这使我感到惊讶。

    (显然,我不应该假设这种事情在所有平台上都可以起作用;这正是Javadoc警告的。)

  2. 如果您怀疑可能存在一些挥之不去的文件锁,请稍等片刻再进行移动/重命名可能会有所帮助。(在安装程序/升级程序的某一点上,我们添加了一个“睡眠”操作和一个不确定的进度条,持续了大约10秒钟,因为某些文件可能挂着服务)。甚至可以执行一个简单的重试机制try renameTo(),然后等待一段时间(可能逐渐增加),直到操作成功或达到某个超时为止。

就我而言,大多数问题似乎都可以通过兼顾以上两者来解决,因此我们根本不需要进行本机内核调用或诸如此类的事情。


查看完整回答
反对 回复 2019-09-21
?
LEATH

TA贡献1936条经验 获得超6个赞

就我而言,这似乎是我自己的应用程序中的死对象,该对象保留了该文件的句柄。因此,该解决方案对我有用:


for (int i = 0; i < 20; i++) {

    if (sourceFile.renameTo(backupFile))

        break;

    System.gc();

    Thread.yield();

}

优点:速度非常快,因为没有Thread.sleep()带有特定的硬编码时间。


缺点:20的限制是一些硬编码的数字。在我所有的测试中,i = 1就足够了。但可以肯定的是,我将其保留为20岁。


查看完整回答
反对 回复 2019-09-21
  • 3 回答
  • 0 关注
  • 909 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信