Как заблокировать файл с помощью java (если возможно)
У меня есть процесс Java, который открывает файл с помощью FileReader. Как я могу запретить другому (Java) процессу открывать этот файл или хотя бы уведомить о том, что второй процесс уже открыт? Это автоматически приводит к тому, что второй процесс получает исключение, если файл открыт (что решает мою проблему) или я должен явно открыть его в первом процессе с каким-то флагом или аргументом?
Чтобы уточнить:
У меня есть приложение Java, в котором перечислены папки и открывается каждый файл в списке для его обработки. Он обрабатывает каждый файл за другим. Обработка каждого файла состоит в его чтении и выполнении некоторых вычислений на основе содержимого, и это занимает около 2 минут. У меня также есть другое приложение Java, которое делает то же самое, но вместо этого записывает в файл. Я хочу, чтобы иметь возможность запускать эти приложения одновременно, поэтому сценарий будет выглядеть следующим образом. ReadApp перечисляет папку и находит файлы A, B, C. Открывает файл A и начинает чтение. WriteApp перечисляет папку и находит файлы A, B, C. Открывает файл A, видит, что это открыто (исключение или любым способом) и переходит в файл B. ReadApp заканчивает файл A и продолжает B. Он видит, что это открыто и продолжается до C. Очень важно, чтобы WriteApp не записывал, в то время как ReadApp читает тот же файл или наоборот. Это разные процессы.
Ответы
Ответ 1
FileChannel.lock - это то, что вы хотите.
FileInputStream in = new FileInputStream(file);
try {
java.nio.channels.FileLock lock = in.getChannel().lock();
try {
Reader reader = new InputStreamReader(in, charset);
...
} finally {
lock.release();
}
} finally {
in.close();
}
(Отказ от ответственности: код не скомпилирован и, конечно, не протестирован.)
Обратите внимание на раздел под названием "зависимости платформы" в API doc для FileLock.
Ответ 2
Не используйте классы в пакете java.io
, вместо этого используйте пакет java.nio
. Последний имеет класс FileLock
. Вы можете применить блокировку к FileChannel
.
try {
// Get a file channel for the file
File file = new File("filename");
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
// Use the file channel to create a lock on the file.
// This method blocks until it can retrieve the lock.
FileLock lock = channel.lock();
/*
use channel.lock OR channel.tryLock();
*/
// Try acquiring the lock without blocking. This method returns
// null or throws an exception if the file is already locked.
try {
lock = channel.tryLock();
} catch (OverlappingFileLockException e) {
// File is already locked in this thread or virtual machine
}
// Release the lock - if it is not null!
if( lock != null ) {
lock.release();
}
// Close the file
channel.close();
} catch (Exception e) {
}
Ответ 3
Если вы можете использовать Java NIO (JDK 1.4 или выше), то я думаю, что вы ищете java.nio.channels.FileChannel.lock()
FileChannel.lock()
Ответ 4
используйте java.nio.channels.FileLock в сочетании с java. nio.channels.FileChannel
Ответ 5
Возможно, это не то, что вы ищете, но в интересах прихода к проблеме под другим углом....
Являются ли эти два процесса Java, которые могут иметь доступ к одному и тому же файлу в одном приложении? Возможно, вы можете просто фильтровать весь доступ к файлу с помощью одного синхронизированного метода (или, что еще лучше, с помощью JSR-166)? Таким образом, вы можете контролировать доступ к файлу и, возможно, даже запросы доступа к очереди.
Ответ 6
Используйте RandomAccessFile, получите его канал, затем вызовите lock(). Канал, предоставляемый входными или выходными потоками, не имеет достаточных привилегий для правильной блокировки. Обязательно вызовите unlock() в блоке finally (закрытие файла не обязательно приведет к блокировке).
Ответ 7
Я нашел ту же проблему несколько лет назад, когда написал приложение, которое потребовало нескольких пользователей MacOS/Windows для совместного использования одних и тех же данных в нескольких файлах.
Блокировка файлов не работала в MacOS, поэтому я создал свой собственный класс "ioFile", который поддерживал собственный регистр доступа к файлам - открывать r/o, открывать r/w и т.д., И кто "владел" блокировкой.
Это единственный способ в то время, когда я мог контролировать доступ разных пользователей на разных компьютерах с использованием разных ОС.
Ответ 8
Ниже приведен пример кода фрагмента, чтобы заблокировать файл, пока он не будет выполнен JVM.
public static void main(String[] args) throws InterruptedException {
File file = new File(FILE_FULL_PATH_NAME);
RandomAccessFile in = null;
try {
in = new RandomAccessFile(file, "rw");
FileLock lock = in.getChannel().lock();
try {
while (in.read() != -1) {
System.out.println(in.readLine());
}
} finally {
lock.release();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ответ 9
Если вы помещаете доступ к файлу в синхронизированном блоке, в него может войти только один экземпляр потока, другие будут ждать, пока он не завершит работу.
public class FileReader{
public void read() {
synchronized (this) {
//put you file access here
}
}
}
Ответ 10
package tips.javabeat.nio.lock;
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class FileLockTest {
public static void main(String[] args) throws Exception {
RandomAccessFile file = null;
FileLock fileLock = null;
try
{
file = new RandomAccessFile("FileToBeLocked", "rw");
FileChannel fileChannel = file.getChannel();
fileLock = fileChannel.tryLock();
if (fileLock != null){
System.out.println("File is locked");
accessTheLockedFile();
}
}finally{
if (fileLock != null){
fileLock.release();
}
}
}
static void accessTheLockedFile(){
try{
FileInputStream input = new FileInputStream("FileToBeLocked");
int data = input.read();
System.out.println(data);
}catch (Exception exception){
exception.printStackTrace();
}
}
Ответ 11
Вы используете java.nio. * API для блокировки файла. Однако это не гарантирует блокировку. Это зависит от того, поддерживает ли базовая ОС блокировку или нет. Как я понимаю Операционные системы, такие как Linux, не поддерживают блокировку, и поэтому вы не можете блокировать, даже если вы используете эти API