如何在 Java 中获取 "ShareDenyWrite" 文件锁
How to acquire a "ShareDenyWrite" File Lock in Java
我需要在 Java 中的文件上获取 SharedDenyWrite 锁。
定义为:"Other applications can open the file for reading but not for writing."
这在 Delphi 中是可能的,只需打开一个文件和参数 "fmSharedDenyWrite"。
但我找不到 Java 等价物。
请注意,使用 FileChannel.tryLock 或 lock(0, Long.MAX_VALUE, true) 获得的独占锁会阻止其他程序读取文件。这对我不起作用。
共享锁( lock(0, Long.MAX_VALUE, false) 不会阻止其他程序写入文件。这对我也不起作用。
这样做的目的是阻止 tortoise svn 和 intellij svn 集成在我的应用程序中打开时通过执行 svn 更新来更新文件内容。
虽然独占锁确实会阻止 svn 更新,但它还会在 intellij 和 notepad++ 中将文件显示为空 - 这会导致后续问题。
同事找到的答案如下:
使用 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
我需要在 Java 中的文件上获取 SharedDenyWrite 锁。 定义为:"Other applications can open the file for reading but not for writing."
这在 Delphi 中是可能的,只需打开一个文件和参数 "fmSharedDenyWrite"。
但我找不到 Java 等价物。
请注意,使用 FileChannel.tryLock 或 lock(0, Long.MAX_VALUE, true) 获得的独占锁会阻止其他程序读取文件。这对我不起作用。
共享锁( lock(0, Long.MAX_VALUE, false) 不会阻止其他程序写入文件。这对我也不起作用。
这样做的目的是阻止 tortoise svn 和 intellij svn 集成在我的应用程序中打开时通过执行 svn 更新来更新文件内容。
虽然独占锁确实会阻止 svn 更新,但它还会在 intellij 和 notepad++ 中将文件显示为空 - 这会导致后续问题。
同事找到的答案如下: 使用 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