Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: ParalifeОтветов: 8

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

Чтобы уточнить

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

  • Вы имеете в виду "процесс", как в процессе (две JVM) или потоке (та же JVM). Влияние на ответ имеет первостепенное значение. Stu Thompson 25.09.2008
  • проверьте пример кода, показывающий решение здесь: stackoverflow.com/a/58871479/5154619 Davi Cavalcanti 15.11.2019

file-iojava

Ответы

Ответ 1 · рейтинг 119 · Tom Hawtin - tackline

FileChannel.lock - это, вероятно, то, что вам нужно.

try (
    FileInputStream in = new FileInputStream(file);
    java.nio.channels.FileLock lock = in.getChannel().lock();
    Reader reader = new InputStreamReader(in, charset)
) {
    ...
}

(Отказ от ответственности: код не компилируется и, конечно же, не тестируется.)

Обратите внимание на раздел "зависимости платформы" в Документация по API для FileLock.

Ответ 2 · рейтинг 62 · ayengin

Не используйте классы в пакете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 · рейтинг 17 · KC Baltz

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

FileChannel.lock ()

Ответ 4 · рейтинг 8 · Matt

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

Ответ 5 · рейтинг 5 · pkaeding

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

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

Ответ 6 · рейтинг 3 · Kevin Day

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

Ответ 7 · рейтинг 1 · Ajay Kumar

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

}

Ответ 8 · Vamsi

Используйте это для unix, если вы переносите с помощью winscp или ftp:

public static void isFileReady(File entry) throws Exception {
        long realFileSize = entry.length();
        long currentFileSize = 0;
        do {
            try (FileInputStream fis = new FileInputStream(entry);) {
                currentFileSize = 0;
                while (fis.available() > 0) {
                    byte[] b = new byte[1024];
                    int nResult = fis.read(b);
                    currentFileSize += nResult;
                    if (nResult == -1)
                        break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("currentFileSize=" + currentFileSize + ", realFileSize=" + realFileSize);
        } while (currentFileSize != realFileSize);
    }

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы