简体   繁体   中英

How to acquire a “ShareDenyWrite” File Lock in Java

I need to acquire a SharedDenyWrite Lock on a File in Java. Defined as: "Other applications can open the file for reading but not for writing."

This is possible in Delphi with just a File open and the parameter "fmSharedDenyWrite".

But I can't find a Java equivalent.

Note that the exlusive Lock gained with FileChannel.tryLock or lock(0, Long.MAX_VALUE, true) stops other programs from reading the file. This does not work for me.

The shared lock ( lock(0, Long.MAX_VALUE, false) does not stop other programs from writing the file. This does not work for me either.

The goal of this is to block tortoise svn and the intellij svn integration to update the file content by doing an svn update, while it is open in my application.

while the exclusive lock does block the svn update, it also shows the file as empty in intellij and notepad++ - which then causes followup problems.

The answer found by colleague is the following: Using the Java Native Access Framework ( https://github.com/java-native-access/jna ) the Win-API can be used to get the correct locking.

This acquires a handle with the shared-read, exklusive write lock:

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

And the following releases the lock:

  Kernel32.INSTANCE.CloseHandle(lock);

To read the content Kernel32.INSTANCE.ReadFile can be used and to write Kernel32.INSTANCE.WriteFile.

Since the default JNA is missing GetFileSizeEx, SetFilePointer and SetEndOfFile this interface can be used to access those methods for more quality of life concerning the writing and reading of the file:

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

The calls can then be made like this:

Set Cursor to start of file:

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

Write data and then set the End of File:

JnaFileAccess.INSTANCE.SetEndOfFile(fileHandle);

Nothing except the interface is required for this, it maps itself to the Win-API

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM