java - 为什么当通过 FileChanel.open() 而不是 RandomAccessFile.getChannel() 获取文件锁时可以移动文件

标签 java nio

我正在测试通过 FileChannel.open() 和 RandonAccessFile.getChanel() 获取的 NIO File Lock。

发现通过FileChannel.open()获取的FileLock可以移动文件,而通过RandonAccessFile.getChanel()获取的FileLock则不能移动。

FileChannel.open()

        File file = new File("../tmp/test.txt");
        FileChannel fileChannel = FileChannel.open(file.toPath(), StandardOpenOption.WRITE);
        FileLock fileLock = fileChannel.lock();
        System.out.println("file locked");
        boolean result = file.renameTo(new File("../tmp/test2.txt"));
        System.out.println("rename result " + result);
        fileLock.release();
        fileChannel.close();

RandonAccessFile.getChanel()

        File file = new File("../tmp/test.txt");
        RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rws");
        FileChannel newChannel = (randomAccessFile).getChannel();
        FileLock fileLock = newChannel.lock();
        System.out.println("File locked");
        boolean result = file.renameTo(new File("../tmp/test2.txt"));
        System.out.println("rename result " + result);

最佳答案

Java 文件锁定的行为是高度特定于平台的,renameTo 的行为也是如此,包括它与显式锁定或以其他方式“使用”的文件的交互。

在 Windows 中,某些文件“打开”操作将锁定整个文件,并且重命名对锁定的文件不起作用。 (事实上​​,我怀疑即使您注释掉了 lock() 调用,使用 getChannel() 的代码版本也会失败。但我没有 Windows机器来测试这个。)

相比之下,Linux 在打开文件时不会锁定文件,并且您可以重命名打开的文件。

如何处理这个问题?

  • 如果你希望你的代码是跨平台的,你需要非常保守。例如,不要尝试重命名应用程序当前打开的文件。重命名之前关闭所有文件“句柄”。

  • 或者,编写代码以了解平台,并根据需要在不同平台上执行不同的操作。 (我无法准确地建议什么,因为您的示例没有告诉我们您实际上想要实现的目标。)

关于java - 为什么当通过 FileChanel.open() 而不是 RandomAccessFile.getChannel() 获取文件锁时可以移动文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58576072/

相关文章:

java.net.SocketTimeoutException : timeout

Glassfish 3.1.2.2 上的 java.lang.NoClassDefFoundError

java - Windows/Linux 框上的文件分隔符问题

java - 将 InputStream 包装到非阻塞 ReadableByteChannel

Java 一次发送多个文件

java - Centos 7中NIO和IO性能问题(第一次和第二次读写)

java - 字符串到对象的转换,

java - 在 MySQL 中设计两个表以在 JPA 中使用

java - 无法从 EditText 获取整数值

java - 将文本文件读取为字符串而不消耗大量内存