Почему File можно перемещать, когда FileChanel.open () получает блокировку файла вместо RandomAccessFile.getChannel () - PullRequest
0 голосов
/ 27 октября 2019

Я тестирую блокировку файлов NIO, полученную с помощью FileChannel.open () и RandonAccessFile.getChanel ().

Обнаружено, что файл, который FileLock получил с помощью FileChannel.open (), можно переместить во время получения FileLock. RandonAccessFile.getChanel () не.

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);

1 Ответ

1 голос
/ 27 октября 2019

Поведение блокировок файлов Java сильно зависит от платформы, как и поведение renameTo, включая его взаимодействие с файлами, которые явно заблокированы или «используются» другими способами.

Вв случае Windows некоторые операции «открытия» файла блокируют весь файл, а переименование не работает с заблокированным файлом. (Действительно, я подозреваю, что версия вашего кода, использующая getChannel(), потерпит неудачу, даже если вы закомментируете вызов lock(). Но у меня нет машины Windows, чтобы это проверить.)

В отличие от этогоLinux не блокирует файлы при их открытии, и вы можете переименовать открытый файл.

Как с этим справиться?

  • Если вы хотите, чтобы ваш кодбыть кроссплатформенным, нужно быть крайне консервативным. Например, не пытайтесь переименовать файл, который в данный момент открыто вашим приложением. Закройте все файловые «дескрипторы» перед тем, как переименовать.

  • В качестве альтернативы, напишите свой код, чтобы быть в курсе платформы, и при необходимости выполнять разные действия на разных платформах. (Я не могу точно сказать, что именно, потому что ваш пример не говорит нам, чего вы на самом деле пытаетесь достичь.)

...