Как я могу заблокировать файл с помощью java (если это возможно)

StackOverflow https://stackoverflow.com/questions/128038

  •  02-07-2019
  •  | 
  •  

Вопрос

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

Чтобы прояснить:

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

Это было полезно?

Решение

Файловый канал.блокировка - это, вероятно, то, что вы хотите.

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 для блокировки файлов.

Другие советы

Не используйте классы в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) {
    }

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

Файловый канал.заблокировать()

Возможно, это не то, что вы ищете, но в интересах подойти к проблеме с другой стороны....

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

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

Я обнаружил ту же проблему несколько лет назад, когда написал приложение, которое требовало от нескольких пользователей macOS / Windows совместного использования одних и тех же данных в нескольких файлах.Блокировка файлов не работала в macOS, поэтому я создал свой собственный класс 'ioFile', который поддерживал свой собственный реестр доступа к файлам - open r / o, open r / w и т.д., и кому "принадлежала" блокировка.Это единственный способ на тот момент, когда я мог контролировать доступ от разных пользователей на разных машинах, использующих разные операционные системы.

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

}

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

public class FileReader{
  public void read() {
    synchronized (this) {
      //put you file access here
    }
  }
}
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();  
        }  

     }  

Вы можете использовать java.nio.* API для блокировки файла.Однако это не гарантирует блокировку, это зависит от того, поддерживает ли базовая ос блокировку или нет. Насколько я понимаю, операционные системы, такие как Linux, не поддерживают блокировку, и, следовательно, вы не можете заблокировать, даже если используете эти API

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top