Java在将文件重命名到另一个文件系统时失败了

11

我们的一个程序在尝试将文件从一个目录移动到另一个目录时出现了错误。经过长时间的调试,我编写了一个小实用程序来移动文件(下面是代码),最终定位到了错误。原来,在本地文件系统上移动文件很好用,但是尝试将文件移动到另一个文件系统会失败。

为什么会这样呢?这个问题可能与平台有关 - 我们在ext3上运行Linux,如果这有影响的话。

还有第二个问题:除了File类的renameTo()方法,我应该使用其他东西吗?看起来似乎它只适用于本地文件系统。

测试(以root身份运行):

touch /tmp/test/afile

java FileMover /tmp/test/afile /root/
The file move was successful

touch /tmp/test/afile

java FileMover /tmp/test/afile /some_other_disk/
The file move was erroneous

代码:

import java.io.File;

public class FileMover {
    public static void main(String arguments[] ) throws Exception {
        boolean success;
        File file = new File(arguments[0]);
        File destinationDir = new File(arguments[1]);
        File destinationFile = new File(destinationDir,file.getName() );
        success = file.renameTo(destinationFile);
        System.out.println("The file move was " + (success?"successful":"erroneous"));
    }
}
4个回答

19

Java 7及以上

使用Files.move(Path source, Path target, CopyOption... opts)

请注意,当在文件系统之间移动文件时,不应提供ATOMIC_MOVE选项。

Java 6及以下

File.renameTo的文档中可以看出:

[...] 重命名操作可能无法将文件从一个文件系统移动到另一个文件系统 [...]

显然的解决方法是通过打开新文件、写入内容并删除旧文件来手动复制文件。

您还可以尝试Apache Commons的FileUtils.moveFile方法。


额...我在写我的答案时没有加载到你的答案 :), moveFile是救星 +1 - mprabhat
您对Apache Commons的建议正是我接下来要采取的步骤。感谢您提供了一份信息丰富的答案,实际上回答了两个问题! - oligofren
1
除了上面提供的优秀答案之外,重命名中使用的系统调用如果oldpath和newpath不在同一个挂载的文件系统上,则返回EXDEV。实际上,像“mv”这样的程序通过执行显式复制操作后跟删除操作来处理此情况。 - ghostkadost
从Java 7开始,您可以使用java.nio.file.Files.move来处理不同的文件系统,但是您不必使用ATOMIC_MOVE选项。请参考https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#move(java.nio.file.Path,%20java.nio.file.Path,%20java.nio.file.CopyOption...)。 - Manuel

6

Javadoc 来拯救:

该方法的许多行为本质上取决于平台:重命名操作可能无法将文件从一个文件系统移动到另一个文件系统,它可能不是原子性的,并且如果目标抽象路径名已经存在,则可能无法成功。应始终检查返回值以确保重命名操作成功。

请注意,Files类定义了move方法以在平台无关的方式移动或重命名文件。


1

来自文档:

重命名由此抽象路径名表示的文件。

该方法的许多行为方面本质上依赖于平台:重命名操作可能无法将文件从一个文件系统移动到另一个文件系统,它可能不是原子性的,并且如果目标抽象路径名已经存在具有相同名称的文件,则可能无法成功。应始终检查返回值以确保重命名操作成功。

如果您想在不同的文件系统之间移动文件,可以使用Apache的moveFile


-1

你的IDer出现错误,因为/some_other_disk/是相对URL而不是完整的URL,所以找不到这个URL。我有一个例子

java FileMover D:\Eclipse33_workspace_j2ee\test\src\a\a.txt D:\Eclipse33_workspace_j2ee\test\src 文件移动成功。

java FileMover D:\Eclipse33_workspace_j2ee\test\src\a\a.txt \Eclipse33_workspace_j2ee\test\src

文件移动错误。

结果是URL错误。


任何以 '/' 开头的路径都是绝对路径(在 Unix 上)。所以不是。请参考上面的答案,找到真正回答问题的内容。 - oligofren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接