Как заблокировать файл с помощью 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()

Ответ 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