Как заблокировать папку в Java перед записью файла? - PullRequest
0 голосов
/ 05 июля 2018

У меня есть сценарий использования, когда несколько потоков могут записать файл в папку. В данный момент я хочу определить, какой файл является последним в этой папке. Поскольку я не могу использовать метку времени, так как она может быть одинаковой для более чем одного файла в папке. Поэтому я хочу заблокировать папку, сгенерировать порядковый номер, посчитав номер файла в папке, записать новый файл, используя сгенерированный порядковый номер, снять блокировку. Это возможно в Java?

Аналогично, при чтении возьмите файл с наибольшим порядковым номером.

Вероятность одновременной записи файла в папку меньше, поэтому производительность не будет проблемой.

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Использование Java SE 7 или выше:

WatchService API позволяет отслеживать файловые операции (создавать, изменять и удалять файлы) в указанном каталоге. В этом сценарии создайте службу наблюдения для отслеживания новых файлов, созданных в определенной папке. Каждый раз, когда создается новый файл, запускается файл, создающий событие, и процесс позволяет выполнять определенные пользователем действия.

Файл уже имеет созданный атрибут времени (java.nio.file.attribute.BasicFileAttributes). Это может быть извлечено как тип java.nio.file.attribute.FileTime, который находится в миллис или может быть более конкретным java.util.concurrent.TimeUnit (это позволяет наносекунда точность). Это дает возможность более точно определить, что является самым новым файлом.

Также есть возможность создать пользовательский определяемый пользователем атрибут файла для любого файла. Атрибут позволяет определять как пару ключ-значение. Это уникальное значение атрибута может быть связано с файлом, чтобы определить, является ли он самым последним. Следующие API позволяют создавать и читать пользовательский атрибут файла: java.nio.file.attribute.UserDefinedFileAttributeView и Files.getFileAttributeView().

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

РЕДАКТИРОВАТЬ (в комплекте):

Использование коллекции для получения последнего файла:

Потокобезопасная коллекция может использоваться для хранения имен файлов (или пути к файлу) и извлечения их LIFO («последний пришел первым - вышел»). Служба наблюдения (или аналогичный процесс) может хранить имя файла (последнего) файла, созданного в папке этой коллекции. Операция чтения просто получает последнее имя файла из этой коллекции и работает с ним. Можно рассмотреть java.util.concurrent.ConcurrentLinkedDeque или LinkedBlockingDeque на основе требований.

РЕДАКТИРОВАТЬ (в комплекте):

Схема возможных решений:

enter image description here

0 голосов
/ 05 июля 2018

Используйте File.createNewFile () в цикле для записи. Потому что это

Атомно создает новый пустой файл с таким абстрактным именем, если и только если файл с таким именем еще не существует. Проверка существования файла и создание файла, если он не существует, - это отдельная операция, которая является атомарной по отношению ко всем другим действиям файловой системы, которые могут повлиять на файл.

Как это:

import java.io.*;
import java.util.*;

public class FileCreator {
    public static void main(String[] args) throws IOException {
        String creatorId = UUID.randomUUID().toString();
        File dir = new File("dir");
        for (int filesCreated = 0; filesCreated < 1000; filesCreated++) {
            File newFile;
            for (int fileIdx = dir.list().length; ; fileIdx++) {
                newFile = new File(dir, "file-" + fileIdx + ".txt");
                if (newFile.createNewFile()) {
                    break;
                }
            }
            try (PrintWriter pw = new PrintWriter(newFile)) {
                pw.println(creatorId);
            }
        }
    }
}

Другой вариант будет Files.createFile (...) . Выдает исключение, если файл уже существует.

Что касается чтения:

Аналогично, при чтении возьмите файл с наибольшим порядковым номером.

В чем тут вопрос? Просто возьмите это.

0 голосов
/ 05 июля 2018

Вы не можете использовать FileLock для каталога, поэтому вам придется обрабатывать блокировки в Java. Вы можете сделать что-то вроде:

private final Object lock = new Object();

public void writeToNext(String dirPath) {
    synchronized(lock) {
        File dir = new File(dirPath);
        List<File> files = Arrays.asList(dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return !pathname.isDirectory();
            }
        }));

        int numFiles = files.size();
        String nextFile = dir.getAbsolutePath() + File.separator + (numFiles + 1) + ".txt"; // get a path for the new file
        System.out.println("Writing to " + nextFile);
        // TODO write to file
    }
}

Примечание

Вы можете реализовать свое решение таким образом, чтобы каждая запись где-то увеличивала счетчик, и вы можете просто использовать его для получения следующего значения; только закажите и ищите последний файл, если счетчик не был инициализирован.

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