Мне нужно написать собственный пакетный переименователь файлов. У меня есть основная часть этого, но я не могу понять, как проверить, открыт ли файл. Я просто использую пакет java.io.File
, и есть метод canWrite()
, но, похоже, он не проверяет, используется ли файл другой программой. Любые идеи о том, как я могу сделать эту работу?
Проверьте, открыт ли файл
Ответ 1
Использование библиотеки ввода-вывода Apache Commons...
boolean isFileUnlocked = false;
try {
org.apache.commons.io.FileUtils.touch(yourFile);
isFileUnlocked = true;
} catch (IOException e) {
isFileUnlocked = false;
}
if(isFileUnlocked){
// Do stuff you need to do with a file that is NOT locked.
} else {
// Do stuff you need to do with a file that IS locked
}
Ответ 2
(Q & A описывает, как работать с блокировками "открытого файла Windows"... не так, как реализовать этот вид блокировки портативно.)
Вся эта проблема чревата проблемами мобильности и условиями гонки:
- Вы можете попробовать использовать FileLock, но это не обязательно поддерживается для вашей ОС и/или файловой системы.
- Похоже, что в Windows вы не сможете использовать FileLock, если другое приложение открыло файл определенным образом.
- Даже если вам удавалось использовать FileLock или что-то еще, у вас все еще есть проблема, что что-то может появиться и открыть файл между вами, проверяющим файл и выполняющим переименование.
Более простое и (возможно) более надежное решение - просто попробовать переименовать (или что бы вы ни пытались сделать) и диагностировать возвращаемое значение и/или любые исключения Java, возникающие из-за открытых файлов.
Примечания:
-
Если вы используете API
Files
вместо APIFile
, вы получите больше информации в случае сбоя. -
В системах, где вам разрешено переименовать (или что-то еще) заблокированный или открытый файл, вы не получите никакого результата или исключения. Операция будет успешной.
Ответ 3
Лучше всего установить исключительную блокировку файла. Если файл открыт другими процессами, вы получите исключение. Например,
File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
// Get an exclusive lock on the whole file
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();
}
Ответ 4
// TO CHECK WHETHER A FILE IS OPENED
// OR NOT (not for .txt files)
// the file we want to check
String fileName = "C:\\Text.xlsx";
File file = new File(fileName);
// try to rename the file with the same name
File sameFileName = new File(fileName);
if(file.renameTo(sameFileName)){
// if the file is renamed
System.out.println("file is closed");
}else{
// if the file didnt accept the renaming operation
System.out.println("file is opened");
}
Ответ 5
Я не думаю, что вы когда-нибудь получите окончательное решение для этого, операционная система не обязательно скажет вам, открыт ли файл или нет.
Вы можете получить пробег из java.nio.channels.FileLock
, хотя javadoc загружается с оговорками.
Ответ 6
org.apache.commons.io.FileUtils.touch(yourFile)
не проверяет, открыт ли ваш файл или нет. Вместо этого он изменяет временную метку файла на текущее время.
Я использовал IOException, и он отлично работает:
try
{
String filePath = "C:\sheet.xlsx";
FileWriter fw = new FileWriter(filePath );
}
catch (IOException e)
{
System.out.println("File is open");
}
Ответ 7
В Windows я нашел ответ fooobar.com/questions/137912/..., используя
fileIsLocked = !file.renameTo(file)
наиболее полезно, так как он избегает ложных срабатываний при обработке защищенных от записи файлов.
Ответ 8
Если файл используется, FileOutputStream fileOutputStream = new FileOutputStream(file);
возвращает java.io.FileNotFoundException с "Процесс не может получить доступ к файлу, потому что он используется другим процессом" в сообщении об исключении.