How can I lock a file using java (if possible)

JavaFile Io

Java Problem Overview


I have a Java process that opens a file using a FileReader. How can I prevent another (Java) process from opening this file, or at least notify that second process that the file is already opened? Does this automatically make the second process get an exception if the file is open (which solves my problem) or do I have to explicitly open it in the first process with some sort of flag or argument?

To clarify:

I have a Java app that lists a folder and opens each file in the listing for processing it. It processes each file after the other. The processing of each file consists of reading it and doing some calculations based on the contents and it takes about 2 minutes. I also have another Java app that does the same thing but instead writes on the file. What I want is to be able to run these apps at the same time so the scenario goes like this. ReadApp lists the folder and finds files A, B, C. It opens file A and starts the reading. WriteApp lists the folder and finds files A, B, C. It opens file A, sees that is is open (by an exception or whatever way) and goes to file B. ReadApp finishes file A and continues to B. It sees that it is open and continues to C. It is crucial that WriteApp doesn't write while ReadApp is reading the same file or vice versa. They are different processes.

Java Solutions


Solution 1 - Java

FileChannel.lock is probably what you want.

try (
    FileInputStream in = new FileInputStream(file);
    java.nio.channels.FileLock lock = in.getChannel().lock();
    Reader reader = new InputStreamReader(in, charset)
) {
    ...
}

(Disclaimer: Code not compiled and certainly not tested.)

Note the section entitled "platform dependencies" in the API doc for FileLock.

Solution 2 - Java

Don't use the classes in thejava.io package, instead use the java.nio package . The latter has a FileLock class. You can apply a lock to a FileChannel.

 try {
        // Get a file channel for the file
        File file = new File("filename");
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
    
        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();

        /*
           use channel.lock OR channel.tryLock();
        */

        // Try acquiring the lock without blocking. This method returns
        // null or throws an exception if the file is already locked.
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }
    
        // Release the lock - if it is not null!
        if( lock != null ) {
            lock.release();
        }
    
        // Close the file
        channel.close();
    } catch (Exception e) {
    }

Solution 3 - Java

If you can use Java NIO (JDK 1.4 or greater), then I think you're looking for java.nio.channels.FileChannel.lock()

FileChannel.lock()

Solution 4 - Java

Solution 5 - Java

This may not be what you are looking for, but in the interest of coming at a problem from another angle....

Are these two Java processes that might want to access the same file in the same application? Perhaps you can just filter all access to the file through a single, synchronized method (or, even better, using JSR-166)? That way, you can control access to the file, and perhaps even queue access requests.

Solution 6 - Java

Use a RandomAccessFile, get it's channel, then call lock(). The channel provided by input or output streams does not have sufficient privileges to lock properly. Be sure to call unlock() in the finally block (closing the file doesn't necessarily release the lock).

Solution 7 - Java

Below is a sample snippet code to lock a file until it's process is done by JVM.

 public static void main(String[] args) throws InterruptedException {
    File file = new File(FILE_FULL_PATH_NAME);
    RandomAccessFile in = null;
    try {
        in = new RandomAccessFile(file, "rw");
        FileLock lock = in.getChannel().lock();
        try {

            while (in.read() != -1) {
                System.out.println(in.readLine());
            }
        } finally {
            lock.release();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Solution 8 - Java

Use this for unix if you are transferring using winscp or ftp:

public static void isFileReady(File entry) throws Exception {
		long realFileSize = entry.length();
		long currentFileSize = 0;
		do {
			try (FileInputStream fis = new FileInputStream(entry);) {
				currentFileSize = 0;
				while (fis.available() > 0) {
					byte[] b = new byte[1024];
					int nResult = fis.read(b);
					currentFileSize += nResult;
					if (nResult == -1)
						break;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			System.out.println("currentFileSize=" + currentFileSize + ", realFileSize=" + realFileSize);
		} while (currentFileSize != realFileSize);
	}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionParalifeView Question on Stackoverflow
Solution 1 - JavaTom Hawtin - tacklineView Answer on Stackoverflow
Solution 2 - JavaayenginView Answer on Stackoverflow
Solution 3 - JavaKC BaltzView Answer on Stackoverflow
Solution 4 - JavaMattView Answer on Stackoverflow
Solution 5 - JavapkaedingView Answer on Stackoverflow
Solution 6 - JavaKevin DayView Answer on Stackoverflow
Solution 7 - JavaAjay KumarView Answer on Stackoverflow
Solution 8 - JavaVamsiView Answer on Stackoverflow