Как получить блокировку файла "ShareDenyWrite" в Java - PullRequest
0 голосов
/ 18 июня 2020

Мне нужно получить блокировку SharedDenyWrite для файла в Java. Определяется как: «Другие приложения могут открывать файл для чтения, но не для записи».

Это возможно в Delphi только с открытым файлом и параметром «fmSharedDenyWrite».

Но Я не могу найти эквивалент Java.

Обратите внимание, что исключительная блокировка, полученная с помощью FileChannel.tryLock или lock (0, Long.MAX_VALUE, true), останавливает чтение файла другими программами. У меня это не работает.

Совместная блокировка (lock (0, Long.MAX_VALUE, false) не мешает другим программам записывать файл. У меня это тоже не работает.

Цель этого состоит в том, чтобы заблокировать черепаху svn и интеграцию intellij svn для обновления содержимого файла, выполнив обновление svn, пока он открыт в моем приложении.

в то время как эксклюзивная блокировка блокирует обновление svn, он также показывает файл как пустой в intellij и notepad ++, что затем вызывает проблемы с отслеживанием.

1 Ответ

0 голосов
/ 26 июня 2020

Ответ, найденный коллегой, следующий: Используя Java Native Access Framework (https://github.com/java-native-access/jna), можно использовать Win-API для получения правильной блокировки.

Это получает дескриптор с эксклюзивной блокировкой записи с общим доступом:

 WinNT.HANDLE lockFile = Kernel32.INSTANCE.CreateFile(filename,
        WinNT.GENERIC_READ | WinNT.GENERIC_WRITE,
        WinNT.FILE_SHARE_READ,
        null,
        WinNT.OPEN_ALWAYS,
        WinNT.FILE_ATTRIBUTE_NORMAL,
        null);

И следующее освобождает блокировку:

  Kernel32.INSTANCE.CloseHandle(lock);

Для чтения содержимого Kernel32.INSTANCE.ReadFile может быть используется и для записи Kernel32.INSTANCE.WriteFile.

Поскольку JNA по умолчанию отсутствует GetFileSizeEx, SetFilePointer и SetEndOfFile, этот интерфейс можно использовать для доступа к этим методам для повышения качества жизни при записи и чтении файла:

package filesystem.jna;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;

public interface JnaFileAccess extends StdCallLibrary {
  JnaFileAccess INSTANCE = Native.load("kernel32", JnaFileAccess.class, W32APIOptions.DEFAULT_OPTIONS);

  boolean GetFileSizeEx(WinNT.HANDLE fileHandle, LongByReference size);

  int SetFilePointer(WinNT.HANDLE fileHandle, long DistanceToMove, Pointer DistanceToMoveHigh, int MoveMethod);

  boolean SetEndOfFile(WinNT.HANDLE fileHandle);
}

Вызовы могут быть выполнены следующим образом:

Установить курсор на начало файла:

JnaFileAccess.INSTANCE.SetFilePointer(fileHandle, 0, null, 0);

Записать данные, а затем установить конец файла:

JnaFileAccess.INSTANCE.SetEndOfFile(fileHandle);

Для этого ничего не требуется, кроме интерфейса, он сопоставляется с Win-API

...