如何在Java中原子重命名文件,即使dest文件已经存在?

2022-09-01 02:32:21

我有一个计算机集群,每个计算机运行一个Java应用程序。

这些 Java 应用程序需要同时访问唯一的文件。resource.txt

我需要在Java中原子地重命名文件,即使已经存在。temp.txtresource.txtresource.txt

删除和重命名不起作用,因为它不是原子的(它会创建一个不存在的小时间范围)。resource.txttemp.txtresource.txt

它应该是跨平台的...

谢谢!


答案 1

对于 Java 1.7+,与 CopyOptions 一起使用“REPLACE_EXISTING”和“ATOMIC_MOVE”。java.nio.file.Files.move(Path source, Path target, CopyOption... options)

有关详细信息,请参阅 API 文档。

例如:

Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE);

答案 2

在Linux上(我相信Solaris和其他UNIX操作系统),Java的File.renameTo()方法将覆盖目标文件(如果存在),但在Windows下不是这种情况。

要成为跨平台,我认为您必须对资源使用文件锁定.txt然后覆盖数据。

文件锁定的行为取决于平台。在某些平台上,文件锁定是建议性的,这意味着除非应用程序检查文件锁定,否则不会阻止它访问该文件。在其他平台上,文件锁定是必需的,这意味着文件锁定会阻止任何应用程序访问该文件。

try {
    // Get a file channel for the file
    File file = new File("filename");
    FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

    // Use the file channel to create a lock on the file.
    // This method blocks until it can retrieve the lock.
    FileLock lock = channel.lock();

    // Try acquiring the lock without blocking. This method returns
    // null or throws an exception if the file is already locked.
    try {
        lock = channel.tryLock();
    } catch (OverlappingFileLockException e) {
        // File is already locked in this thread or virtual machine
    }

    // Release the lock
    lock.release();

    // Close the file
    channel.close();
} catch (Exception e) {
}

默认情况下,Linux使用自愿锁定,而Windows则强制使用它。也许您可以检测到操作系统,并在UNIX下使用debredTo()以及Windows的一些锁定代码?

还有一种方法可以在Linux下为特定文件启用强制锁定,但它有点晦涩难懂。您必须将模式位设置得恰到好处。

Linux,遵循System V(请参阅System V接口定义(SVID)版本3),允许没有组执行权限的文件的sgid位将文件标记为强制锁定