I've got e:\myfile.txt with some random contents:
abcabcxyz...abc
Then I try to use nio FileLock
like below:
import java.io.*;
import java.nio.channels.*;
public class FileLockTest{
public static void main(String[] args){
FileLock lock = null;
try(FileChannel ch=new FileOutputStream(args[0]).getChannel())
{
lock=ch.lock();//No param exclusive lock.
//lock(0L,ch.size(),true) for shared lock.
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
if(lock!=null){
try{
lock.release();//throws exception!
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
Upon running it and I got:
PS> java FileLockTest e:\myfile.txt
java.nio.channels.ClosedChannelException
at sun.nio.ch.FileLockImpl.release(Unknown Source)
at FileLockTest.main(FileLockTest.java:17)
I open myfile.txt again, all contents are missing, seems
FileLock
has truncated it, really strange to me.
Could you help to explain what goes wrong here?
CodePudding user response:
Your content is missing because you've accessed your file with an output stream in writing mode which erases all the previous content before performing any writing operation.
If you need to keep the existing content and add new information within your file, then you need to open it in "append" mode by passing a second boolean parameter with value true
.
FileChannel ch = new FileOutputStream(args[0], true)
Also, as already said in the comments, what is giving you the ClosedChannelException
is the fact that FileLock
is bound to a file connection which has been already closed once you've exited the try
block of your try-with
statement. In fact, once you've reached your finally
block the connection has been closed already and any attempt to release a lock on a closed connection will fail.
So to answer your question, it's not the lock which erases your data, but rather the way how you access your file. Besides, since both FileOutputStream
and FileLock
implement AutoClosable
, you could include both of them in the try-with
statement and rewrite your code like this:
public static void main(String[] args) {
try (FileChannel ch = new FileOutputStream(args[0], true).getChannel();
FileLock lock = ch.lock()) {
//do your operations....
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}