Issue
I have a process that will be called rather frequently from cron to read a file that has certain move related commands in it. My process needs to read and write to this data file - and keep it locked to prevent other processes from touching it during this time. A completely separate process can be executed by a user to (potential) write/append to this same data file. I want these two processes to play nice and only access the file one at a time.
The nio FileLock seemed to be what I needed (short of writing my own semaphore type files), but I'm having trouble locking it for reading. I can lock and write just fine, but when attempting to create lock when reading I get a NonWritableChannelException. Is it even possible to lock a file for reading? Seems like a RandomAccessFile is closer to what I need, but I don't see how to implement that.
Here is the code that fails:
FileInputStream fin = new FileInputStream(f);
FileLock fl = fin.getChannel().tryLock();
if(fl != null)
{
System.out.println("Locked File");
BufferedReader in = new BufferedReader(new InputStreamReader(fin));
System.out.println(in.readLine());
...
The exception is thrown on the FileLock line.
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
at java.nio.channels.FileChannel.tryLock(Unknown Source)
at Mover.run(Mover.java:74)
at java.lang.Thread.run(Unknown Source)
Looking at the JavaDocs, it says
Unchecked exception thrown when an attempt is made to write to a channel that was not originally opened for writing.
But I don't necessarily need to write to it. When I try creating a FileOutpuStream, etc. for writing purposes it is happy until I try to open a FileInputStream on the same file.
Solution
- Are you aware that locking the file won't keep other processes from touching it unless they also use locks?
- You have to lock via a writable channel. Get the lock via a
RandomAccessFile
in "rw" mode and then open yourFileInputStream
. Make sure to close both!
Answered By - user207421
Answer Checked By - Senaida (JavaFixing Volunteer)