Как проверить, открыт ли файл другим процессом (Java/Linux)?
Я пытаюсь проверить, открыт ли какой-либо java.io.File внешней программой. В окнах я использую этот простой трюк:
try {
FileOutputStream fos = new FileOutputStream(file);
// -> file was closed
} catch(IOException e) {
// -> file still open
}
Я знаю, что системы на основе unix позволяют открывать файлы в нескольких процессах... Есть ли подобный трюк для достижения того же результата для систем на основе UNIX?
Любая помощь/взлома высоко ценится: -)
Ответы
Ответ 1
Вот пример использования lsof для систем на основе UNIX:
public static boolean isFileClosed(File file) {
try {
Process plsof = new ProcessBuilder(new String[]{"lsof", "|", "grep", file.getAbsolutePath()}).start();
BufferedReader reader = new BufferedReader(new InputStreamReader(plsof.getInputStream()));
String line;
while((line=reader.readLine())!=null) {
if(line.contains(file.getAbsolutePath())) {
reader.close();
plsof.destroy();
return false;
}
}
} catch(Exception ex) {
// TODO: handle exception ...
}
reader.close();
plsof.destroy();
return true;
}
Надеюсь, что это поможет.
Ответ 2
Вы можете запустить из программы Java утилиту lsof
Unix, которая сообщает вам, какой процесс использует файл, а затем анализирует его вывод. Для запуска программы из Java-кода используйте, например, классы Runtime
, Process
, ProcessBuilder
. Примечание: ваша Java-программа не будет переносимой в этом случае, что противоречит концепции переносимости, поэтому дважды подумайте, действительно ли вам это нужно:)
Ответ 3
Это также должно работать для систем Windows. Но внимание не работает для Linux!
private boolean isFileClosed(File file) {
boolean closed;
Channel channel = null;
try {
channel = new RandomAccessFile(file, "rw").getChannel();
closed = true;
} catch(Exception ex) {
closed = false;
} finally {
if(channel!=null) {
try {
channel.close();
} catch (IOException ex) {
// exception handling
}
}
}
return closed;
}
Ответ 4
Спасибо за оригинальное предложение. У меня есть небольшое обновление, которое несколько важно для этого метода:
FileOutputStream fos = null;
try {
// Make sure that the output stream is in Append mode. Otherwise you will
// truncate your file, which probably isn't what you want to do :-)
fos = new FileOutputStream(file, true);
// -> file was closed
} catch(IOException e) {
// -> file still open
} finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Cheers, Gumbatron
Ответ 5
Вы можете попробовать этот код типа семафора для блокировки файлов с помощью @ZZ Coder
File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
FileLock lock = channel.lock();
try {
lock = channel.tryLock();
// Ok. You get the lock
} catch (OverlappingFileLockException e) {
// File is open by someone else
} finally {
lock.release();
}