Как я могу заблокировать файл с помощью Java (если это возможно) - PullRequest
108 голосов
/ 24 сентября 2008

У меня есть процесс Java, который открывает файл с помощью FileReader. Как я могу запретить другому (Java) процессу открывать этот файл или хотя бы уведомить второй процесс о том, что файл уже открыт? Это автоматически заставляет второй процесс получить исключение, если файл открыт (что решает мою проблему), или мне нужно явно открыть его в первом процессе с каким-то флагом или аргументом?

Для уточнения:

У меня есть приложение Java, которое перечисляет папку и открывает каждый файл в списке для его обработки. Он обрабатывает каждый файл за другим. Обработка каждого файла состоит из его чтения и выполнения некоторых вычислений на основе содержимого, и это занимает около 2 минут. У меня также есть другое приложение Java, которое делает то же самое, но вместо этого пишет в файл. Я хочу иметь возможность запускать эти приложения одновременно, чтобы сценарий развивался следующим образом. ReadApp перечисляет папку и находит файлы A, B, C. Он открывает файл A и начинает чтение. WriteApp выводит список папок и находит файлы A, B, C. Он открывает файл A, видит, что он открыт (по исключению или любым другим способом), и переходит к файлу B. ReadApp заканчивает файл A и продолжает B. открыт и продолжает C. Это очень важно, что WriteApp не пишет, пока ReadApp читает тот же файл или наоборот. Это разные процессы.

Ответы [ 11 ]

105 голосов
/ 24 сентября 2008

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 для FileLock .

50 голосов
/ 26 января 2012

Не используйте классы в пакете 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) {
    }
16 голосов
/ 24 сентября 2008

Если вы можете использовать Java NIO ( JDK 1.4 или выше ), то я думаю, что вы ищете java.nio.channels.FileChannel.lock()

FileChannel.lock ()

6 голосов
/ 24 сентября 2008

использовать java.nio.channels.FileLock в сочетании с java.nio.channels.FileChannel

5 голосов
/ 25 сентября 2008

Это может быть не то, что вы ищете, но в интересах решения проблемы под другим углом ...

Являются ли эти два процесса Java, которые могут захотеть получить доступ к одному и тому же файлу, в одном приложении? Возможно, вы можете просто отфильтровать весь доступ к файлу с помощью одного синхронизированного метода (или, что еще лучше, используя JSR-166 )? Таким образом, вы можете контролировать доступ к файлу и, возможно, даже запросы доступа к очереди.

3 голосов
/ 25 сентября 2008

Используйте RandomAccessFile, получите его канал, затем вызовите lock (). Канал, предоставленный входными или выходными потоками, не имеет достаточных привилегий для правильной блокировки. Обязательно вызовите unlock () в блоке finally (закрытие файла не обязательно снимает блокировку).

0 голосов
/ 24 мая 2017

Ниже приведен пример кода фрагмента для блокировки файла, пока его обработка не будет выполнена 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();
        }
    }

}
0 голосов
/ 08 июня 2015
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();  
        }  

     }  
0 голосов
/ 20 мая 2014

Я обнаружил ту же проблему несколько лет назад, когда писал приложение, которое требовало, чтобы несколько пользователей в MacOS / Windows совместно использовали одни и те же данные в нескольких файлах. Блокировка файлов не работала на MacOS, поэтому я создал свой собственный класс ioFile, который поддерживал свой собственный регистр доступа к файлам - open r / o, open r / w и т. Д., И кто «владел» блокировкой. Это единственный способ в то время, когда я мог контролировать доступ от разных пользователей на разных машинах, используя разные ОС.

0 голосов
/ 24 февраля 2012

Если вы поместите свой доступ к файлу в синхронизированный блок, в него может войти только один экземпляр потока, другие будут ждать, пока один не закончит свою работу.

public class FileReader{
  public void read() {
    synchronized (this) {
      //put you file access here
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...