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?
Your content is missing because you've opened your file with an output stream in write
mode instead of append
. When opening a file in write
mode, the content previously written is erased from the file. While in append
mode, the content is kept and any new write is added at the end.
In your case, since you're using a FileOutputStream
, you need to instantiate ch
with the two-parameter constructor and pass true
to append
. Otherwise, the stream will always be constructed in write
mode.
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 channel that has already been closed. In fact, once you reach the finally
block, the channel is no longer open, and any attempt to release a lock on a closed channel simply fails.
So, to answer your question, it's not the lock which erases your data, but rather the way how you access the file. Besides, since both FileOutputStream
and FileLock
implement the AutoClosable
interface, 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();
}
}