我的Java程序需要读取一个可能被其他写入程序锁定的文件。我需要检查文件是否被锁定,如果是,则等待直到它释放。如何实现这一点?
该Java程序正在运行在Windows 2000服务器上。
应该在Windows中工作:
File file = new File("file.txt");
boolean fileIsNotLocked = file.renameTo(file);
在Windows下使用Sun的JVM,FileLocks应该是能够正常工作的,尽管JavaDocs对其可靠性描述得相当模糊(与系统相关)。
然而,如果你的Java程序只需要识别某些“其他”程序是否锁定了文件,那么你不需要费力去处理FileLocks,而是可以尝试写入文件,如果文件已被锁定,则写入会失败。最好在实际系统上尝试一下,但我看到以下行为:
File f = new File("some-locked-file.txt");
System.out.println(f.canWrite()); // -> true
new FileOutputStream(f); // -> throws a FileNotFoundException
这很奇怪,但是如果你不把平台独立性看得太高,并且你的系统显示相同的行为,你可以将其组合在一个实用函数中。
当前的 Java 版本中,不幸的是没有办法得知文件状态的变化,所以如果你需要等待文件写入,你必须不时地尝试检查其他进程是否释放了文件锁。我不确定,但是在 Java 7 中,可能可以使用新的 WatchService 来获取这样的变化通知。
new FileOutputStream(file, true)
以保留文件内容(如果文件存在)。 - Dimitar II如果可能有多个进程(可以是Java和非Java的混合)在使用文件,则使用文件锁定(FileLock)
。成功使用文件锁的关键是记住它们仅仅是“建议性的”。如果您忘记了,锁定将被保证可见,但它不会阻止您对文件进行操作。所有访问该文件的进程都应该设计为使用锁定协议。
最好的方法是使用FileLock,但在我的情况下(jdk 1.6),我尝试并成功了:
public static boolean isFileUnlocked(File file) {
try {
FileInputStream in = new FileInputStream(file);
if (in!=null) in.close();
return true;
} catch (FileNotFoundException e) {
return false;
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
if (in != null)
绝对不必要,这个条件将始终为真。 - bvdb您可以尝试对文件进行独占锁定。只要无法获得独占锁定,就表示另一个程序已经对该文件进行了锁定(独占或共享)。
我尝试了 @vlad 提供的方法,在 Windows 上访问 Linux Smb 共享文件,对于像 Excel 这样的锁定功能已经足够了,但对于一些编辑器则不行。为了测试两种情况,我添加了第二部分(重命名)。
Original Answer 翻译成“最初的回答”。
public static boolean testLockFile(File p_fi) {
boolean bLocked = false;
try (RandomAccessFile fis = new RandomAccessFile(p_fi, "rw")) {
FileLock lck = fis.getChannel().lock();
lck.release();
} catch (Exception ex) {
bLocked = true;
}
if (bLocked)
return bLocked;
// try further with rename
String parent = p_fi.getParent();
String rnd = UUID.randomUUID().toString();
File newName = new File(parent + "/" + rnd);
if (p_fi.renameTo(newName)) {
newName.renameTo(p_fi);
} else
bLocked = true;
return bLocked;
}
最初的回答:
new RandomAccessFile(file, "rw")
java.io.FileNotFoundException: <fileName> (The process cannot access the file because it is being used by another process)
。这样,您就不需要仅为检查而打开/关闭流。改进了Amjad Abdul-Ghani的答案,我发现在尝试从文件中读取数据之前没有产生任何错误。
public static boolean isFilelocked(File file) {
try {
try (FileInputStream in = new FileInputStream(file)) {
in.read();
return false;
}
} catch (FileNotFoundException e) {
return file.exists();
} catch (IOException ioe) {
return true;
}
}
仅在Windows上测试过: 您可以按照增强的venergiac答案检查文件是否被锁定: 检查(file.exist())文件是否存在,但如果出现FileNotFoundException,则表示已被锁定! 您将注意到此消息(进程无法访问文件,因为另一个进程正在使用它)
public static boolean isFilelocked(File file) {
try {
FileInputStream in = new FileInputStream(file);
in.close();
return false;
} catch (FileNotFoundException e) {
if(file.exist()){
return true;
}
return false;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}