我有 e:\myfile.txt,其中包含一些随机内容:
abcabcxyz...abc
然后我尝试使用 nio
FileLock
,如下所示:
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();
}
}
}
}
}
运行后我得到:
PS> java FileLockTest e:\myfile.txt
java.nio.channels.ClosedChannelException
at sun.nio.ch.FileLockImpl.release(Unknown Source)
at FileLockTest.main(FileLockTest.java:17)
我再次打开myfile.txt,似乎所有内容都丢失了
FileLock
已截断它,对我来说真的很奇怪。
您能帮忙解释一下这里出了什么问题吗?
您的内容丢失,因为您使用输出流以
write
模式而不是 append
打开文件。当以write
模式打开文件时,先前写入的内容将从文件中删除。在 append
模式下,内容将被保留,任何新写入都会添加到末尾。
在您的情况下,由于您使用的是
FileOutputStream
,因此您需要使用 双参数构造函数实例化
ch
并将 true
传递给 append
。否则,流将始终以 write
模式构建。
FileChannel ch = new FileOutputStream(args[0], true)
此外,正如评论中已经说过的,给您
ClosedChannelException
的事实是 FileLock
绑定到已关闭的文件通道。事实上,一旦到达 finally
块,通道就已经关闭,任何释放已关闭通道上的锁的尝试都会失败。
所以,回答你的问题,删除你数据的不是锁,而是你访问文件的方式。此外,由于
FileOutputStream
和 FileLock
都实现了 AutoClosable
接口,因此您可以将它们都包含在 try-with
语句中,并像这样重写代码:
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();
}
}