Locking Files in Java
Join the DZone community and get the full member experience.
In most I/O -based applications, we deal with concurrency, where several processes do reads/writes to a file. While reading/writing to a file, we need to ensure that it is not being used by other processes to ensure data integrity. The Java NIO API provides file locking at the operating system level (hence it is visible to other processes) so that other processes cannot access the file. The NIO API allows the obtaining of shared or exclusive locks on either whole file or part of the file.
In Java, a file lock can be obtained using FileChannel , which provides two methods — lock() and tryLock() — for this purpose.
The lock() method acquires an exclusive lock on entire file, whereas the lock(long position, long size, boolean shared) method can be used to acquire a lock on the given region of a ile. These two methods will block until the lock is obtained. Meanwhile, the methods tryLock() and tryLock(long position, long size, boolean shared) do the same, but they don’t block and they return immediately.
These methods return a FileLock object, which can be used further to control the lock and, at the end, to release a lock. In the case of the tryLock() method, if it fails to acquire a lock due to overlapping (lock already held by other process), then it returns null; if it fails due to some other reason, then an appropriate exception is thrown.
Now let us look at an example:
package com.test.nio.filelock; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class FileLockTest < private static final Log LOG = LogFactory.getLog(FileLockTest.class); private static FileChannel fc; private static RandomAccessFile randomAccessFile; public FileLockTest(String fileName) throws FileNotFoundException < randomAccessFile = new RandomAccessFile(fileName, "rw"); >public void writeToFileWithLock(String data) < fc = randomAccessFile.getChannel(); ByteBuffer buffer = null; try (fc; randomAccessFile; FileLock fileLock = fc.tryLock()) < if (null != fileLock) < buffer = ByteBuffer.wrap(data.getBytes()); buffer.put(data.toString().getBytes()); buffer.flip(); while (buffer.hasRemaining()) fc.write(buffer); >> catch (OverlappingFileLockException | IOException ex) < LOG.error("Exception occured while trying to get a lock on File. " + ex.getMessage()); >> >
Don’t forget to lock the file when your application has several processes that can read/write. Happy learning!
Opinions expressed by DZone contributors are their own.
Blog
In a multi-threaded application where multiple threads are accessing a resource at the same time, it becomes necessary to handle concurrent modifications.
Suppose a file is being written by a thread and at the same time it is being read by another thread. In such case, the thread reading the file will not have the updated contents .
Similarly, if two threads are writing a file at the same time, then there are chances of the file becoming corrupt .
To avoid such situations, there should be a mechanism that locks the file while writing or reading in java. Fortunately, java NIO has the facility to lock a file and this article will explain how to to that.
java nio file lock
java.nio.FileChannel provides a channel for reading and writing files. This class also has methods to acquire locks on the file that is pointed by the underlying channel.
When a lock is acquired on a file by a thread or process, then any other thread or process cannot access the file till the thread or process holding the lock either releases it or the process terminates.
Following are the two methods of this class that provide an exclusive lock to a file.
- lock: Tries to acquire lock on the file represented by the underlying channel. This method blocks if the lock is not immediately available. This method may throw below exceptions
- java.nio.channels.ClosedChannelException : If the channel is closed when it tries to gain the lock.
- java.nio.channels.OverlappingFileLockException : If another thread or process is holding a lock at the same region of the file or over the entire file.
- java.nio.channels.NonWritableChannelException : If the channel is not opened in write mode.
- java.nio.channels.FileLockInterruptionException : If a thread is blocked for getting a lock and in the mean time it is interrupted.
- java.io.IOException : When an IO error occurs other than above.
- tryLock: Tries to acquire lock on the file represented by the underlying channel. This method does not block if the lock is not available and returns immediately. It returns null if it fails to acquire lock or throws appropriate exception out of the below.
- java.nio.channels.ClosedChannelException : Thrown if the channel is closed at the time of acquiring lock.
- java.nio.channels.OverlappingFileLockException : If another thread or process is holding a lock at the same region of the file or over the entire file.
- java.io.IOException : When an IO error occurs other than above.
Note: Both the above methods also have an overloaded version which allows to lock a block of file. It accepts the position and the range of the file that it will try to get a lock on.
lock file java example
Below program is used to lock a file before writing using java.nio.FileChannel .
import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.io.File; public class FileLockExample { public static main(String[] args) { // open file in read-write mode RandomAccessFile randomAccessFile = new RandomAccessFile( new File("e:/demo.txt"), "rw"); try { // get channel FileChannel channel = randomAccessFile.getChannel(); // get lock FileLock tryLock = channel.lock(); String data = "text to write"; // write to file randomAccessFile.write(data.getBytes()); // release lock tryLock.release(); // close file randomAccessFile.close(); } catch (IOException e) { e.printStackTrace(); } } }
Above method uses java.io.RandomAccessFile for writing to a file, you can also use other methods of writing a file in java in the same place.
While the file is locked for writing, try to read it in another thread using any of the file reading methods in java and you will get the below exception
java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.base/java.io.FileInputStream.readBytes(Native Method)
at java.base/java.io.FileInputStream.read(FileInputStream.java:279)
at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.base/sun.nio.cs.StreamDecoder.read0(StreamDecoder.java:127)
at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:112)
at java.base/java.io.InputStreamReader.read(InputStreamReader.java:168)
which clearly shows that the file is locked.
Similarly, if one thread or process is holding the file’s lock and you try to get another lock in a different thread, then you will get a java.nio.channels.OverlappingFileLockException as below
Exception in thread “Thread-1” java.nio.channels.OverlappingFileLockException
at java.base/sun.nio.ch.FileLockTable.checkList(FileLockTable.java:229)
at java.base/sun.nio.ch.FileLockTable.add(FileLockTable.java:123)
at java.base/sun.nio.ch.FileChannelImpl.lock(FileChannelImpl.java:1109)
A file can also be locked for only reading. Just change the mode when creating an object of type java.io.RandomAccessFile to read.
Hit the clap if you liked the article.
Share if it’s worth .
Locking Files using Java
File Locking can be achieved in java by making use of the New I/O API (nio). Before the advent of New I/O API, there was no direct support in Java for locking a file. It is important to understand that File locking is hugely dependent on the native operating system on which the program is executing.
File Locks can either be exclusive or shared. An exclusive lock can be acquired on a file only if there are no processes or applications accessing the file. It is possible for one or more processes to have any number of locks on the same file but in different region of a file in the case of a shared lock. Some operating systems doesn’t support the concept of shared locking.
Java provides lock() and tryLock() methods in FileChannel class for getting a lock over the file object. Whether the lock is an exclusive lock or a shared lock depends on the flavor of the methods taking arguments which represents the region of the file to be locked. The method lock() blocks execution until it gets a lock whereas the method tryLock() doesn’t block and returns immediately. If a lock cannot be cannot be acquired on a file, then the tryLock() method will return null.
package tips.javabeat.nio.lock; import java.io.*; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; public class FileLockTest < public static void main(String[] args) throws Exception < RandomAccessFile file = null; FileLock fileLock = null; try < file = new RandomAccessFile("FileToBeLocked", "rw"); FileChannel fileChannel = file.getChannel(); fileLock = fileChannel.tryLock(); if (fileLock != null)< System.out.println("File is locked"); accessTheLockedFile(); >>finally < if (fileLock != null)< fileLock.release(); >> > static void accessTheLockedFile()< try< FileInputStream input = new FileInputStream("FileToBeLocked"); int data = input.read(); System.out.println(data); >catch (Exception exception) < exception.printStackTrace(); >> >
The above program tries to lock a file called “FileToBeLocked” by calling the lock() method on the associated File Channel object. The lock() method blocks the thread until it gets a lock on the file. Then, in order to ensure that the file is locked, the method accessTheLockedFile() is called which tries to read the file contents. Since the lock acquired is an exclusive lock, an IOException is thrown.
About Krishna Srinivasan
He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.