Проверьте, заблокирован ли файл в Java
Моя программа Java хочет прочитать файл, который может быть заблокирован другой программой, записывающей в нее. Мне нужно проверить, заблокирован ли файл, и если да, подождите, пока он будет бесплатным. Как достичь этого?
Программа Java работает на сервере Windows 2000.
Ответы
Ответ 1
В 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 для получения информации об этих изменениях.
Ответ 2
Должен работать в Windows:
File file = new File("file.txt");
boolean fileIsNotLocked = file.renameTo(file);
Ответ 3
Используйте FileLock
во всех приложениях Java, используя этот файл, и запускайте их в одной и той же JVM. В противном случае это невозможно сделать надежно.
Ответ 4
Если несколько процессов (которые могут быть смешением Java и не-Java) могут использовать файл, используйте FileLock
, Ключом к успешному использованию блокировок файлов является помнить, что они только "консультативные". Блокировка гарантированно будет видна, если вы ее проверите, но это не помешает вам делать что-то в файле, если вы забудете. Все процессы, которые обращаются к файлу, должны быть разработаны для использования протокола блокировки.
Ответ 5
Вы можете попытаться получить эксклюзивную блокировку файла. Пока исключительная блокировка не может быть получена, другая программа имеет блокировку (эксклюзивную или разделяемую) в файле.
Ответ 6
Лучший способ - использовать 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;
}
Ответ 7
Проверено только на окнах:
вы можете проверить, заблокирован ли файл как следующий расширенный ответ venergiac:
check for (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;
}
Ответ 8
Улучшенный ответ Амджада Абдул-Гани, я обнаружил, что никаких ошибок не возникало до попытки чтения из файла
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;
}
}
Ответ 9
Я попробовал комбинацию ответов (@vlad) на окнах с доступом к Linux Smb share, и это сработало для меня. Первой части было достаточно для блокировки, как в Excel, но не для некоторых редакторов. Я добавил вторую часть (переименовать) для тестирования обеих ситуаций.
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;
}