A file is one of the oldest ways to store data and share data but if you are
working in a shared file i.e a file that can be read or write by multiple
readers and writers, you need to make sure that the file is
locked before you try to write on it. This is needed to ensure that
someone doesn't overwrite the data you are writing. Fortunately, Java provides
a mechanism to lock a file before writing using the
FileLock
interface. You can get the handle of
FileLock
by using
FileChannel
for writing to a file. The
FileChannel
class is generally used to write faster in a large file and one of the common
ways to write binary data in Java.
In order to lock the file before writing, you need to call the tryLock() method on FileChannel. This method attempts to acquire an exclusive lock on this channel's file. It returns a lock object representing the newly acquired lock, or null if the lock could not be acquired because another program holds an overlapping lock.
This is a non-blocking method and an invocation always returns immediately, either having acquired a lock on the requested region or having failed to do so. If it fails to acquire a lock because an overlapping lock is held by another program then it returns null.
If it fails to acquire a lock for any other reason then an appropriate exception is thrown.
For example, It will throw the OverlappingFileLockException - If a lock that overlaps the requested region is already held by this Java virtual machine, or if another thread is already blocked in this method and is attempting to lock an overlapping region and ClosedChannelException if this channel is closed.
You need to ensure that those exceptions are handled properly and if you are not sure why and how to handle exceptions in Java, I suggest you go through the Error and Exception section of the Complete Java Masterclass course by Udemy. You can also see this review to learn more about that Java course and whether it's worth it or not.
In this program, we have created a RandomAccessFile called "accounts.txt" and then retrieved the FileChannel by calling the getChannel() method on it. In order to lock the file before writing into it, we have called the tryLock() method which will acquire the lock.
After acquiring the lock we write some characters into the file and before releasing the lock by calling lock.release() we made our program sleep for 1 hour using TimeUnit.sleep() method.
In order to lock the file before writing, you need to call the tryLock() method on FileChannel. This method attempts to acquire an exclusive lock on this channel's file. It returns a lock object representing the newly acquired lock, or null if the lock could not be acquired because another program holds an overlapping lock.
This is a non-blocking method and an invocation always returns immediately, either having acquired a lock on the requested region or having failed to do so. If it fails to acquire a lock because an overlapping lock is held by another program then it returns null.
If it fails to acquire a lock for any other reason then an appropriate exception is thrown.
For example, It will throw the OverlappingFileLockException - If a lock that overlaps the requested region is already held by this Java virtual machine, or if another thread is already blocked in this method and is attempting to lock an overlapping region and ClosedChannelException if this channel is closed.
You need to ensure that those exceptions are handled properly and if you are not sure why and how to handle exceptions in Java, I suggest you go through the Error and Exception section of the Complete Java Masterclass course by Udemy. You can also see this review to learn more about that Java course and whether it's worth it or not.
Java Program to lock a file before writing
Now that we understand that we can use FileChannel's tryLock() method and FileLock interface to lock a file before writing, let's see the program in action. This will help you to understand the concept better.import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import java.util.concurrent.TimeUnit; /* * Java Program to lock a file before writing into it. */ public class Demo { public static void main(String[] args) throws Exception { RandomAccessFile file = new RandomAccessFile("accounts.txt", "rw"); FileChannel channel = file.getChannel(); FileLock lock = null; try { lock = channel.tryLock(); } catch (final OverlappingFileLockException e) { file.close(); channel.close(); } file.writeChars("writing after lock"); TimeUnit.HOURS.sleep(1); lock.release(); file.close(); channel.close(); } }
In this program, we have created a RandomAccessFile called "accounts.txt" and then retrieved the FileChannel by calling the getChannel() method on it. In order to lock the file before writing into it, we have called the tryLock() method which will acquire the lock.
After acquiring the lock we write some characters into the file and before releasing the lock by calling lock.release() we made our program sleep for 1 hour using TimeUnit.sleep() method.
You can also use the
Thread.sleep()
method here but I prefer TimeUnit because it's explicitly on how much time the
thread is going to wait.
This part is important to demonstrate what will happen if another program is writing into the file at the same time.
When you first run this program, it will create an accounts.txt file in your project directory and when you open the file you can see the content but the program will not finish it will keep running because of the sleep we have put in there.
Then we try to run the program again and at this time, you will see the following error:
Exception in thread "main" java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.io.RandomAccessFile.writeBytes(Native Method)
at java.io.RandomAccessFile.writeChars(RandomAccessFile.java:1123)
at Demo.main(Demo.java:26)
This happens because the earlier program hasn't released the lock yet. Remember it was paused before calling the lock.release() method.
This becomes more clear with the following screenshot from Eclipse IDE, where you can see that the earlier program is still running (instance 1) which locked the file, and hence when you run the program again, it died with the above error related to file locking:
That's all about how to lock a file before writing in Java. If you are not the exclusive writer on the file or you are working with a shared file then you should always lock the file before writing data into it. Failing to do may result in file corruption and data loss.
You should also make sure to release the lock once you are done with your writing into the file and provide appropriate exception handling to catch OverlappingFileLockException and IOException.
Other Java and File tutorials you may like to explore
How to create a ZIP file in Java?
How to write to a file in Java?
How to append text into an existing file in Java?
How to read from an Excel File in Java using Apache POI
How to read a text file into ArrayList in Java?
Thanks for reading this article, if you like my explanation of how to lock a file before writing data into it then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note.
This part is important to demonstrate what will happen if another program is writing into the file at the same time.
When you first run this program, it will create an accounts.txt file in your project directory and when you open the file you can see the content but the program will not finish it will keep running because of the sleep we have put in there.
Then we try to run the program again and at this time, you will see the following error:
Exception in thread "main" java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.io.RandomAccessFile.writeBytes(Native Method)
at java.io.RandomAccessFile.writeChars(RandomAccessFile.java:1123)
at Demo.main(Demo.java:26)
This happens because the earlier program hasn't released the lock yet. Remember it was paused before calling the lock.release() method.
This becomes more clear with the following screenshot from Eclipse IDE, where you can see that the earlier program is still running (instance 1) which locked the file, and hence when you run the program again, it died with the above error related to file locking:
That's all about how to lock a file before writing in Java. If you are not the exclusive writer on the file or you are working with a shared file then you should always lock the file before writing data into it. Failing to do may result in file corruption and data loss.
You should also make sure to release the lock once you are done with your writing into the file and provide appropriate exception handling to catch OverlappingFileLockException and IOException.
Other Java and File tutorials you may like to explore
How to create a ZIP file in Java?
How to write to a file in Java?
How to append text into an existing file in Java?
How to read from an Excel File in Java using Apache POI
How to read a text file into ArrayList in Java?
Thanks for reading this article, if you like my explanation of how to lock a file before writing data into it then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note.
No comments:
Post a Comment
Feel free to comment, ask questions if you have any doubt.