Какой самый простой способ отследить изменение в папке в Java? - PullRequest
5 голосов
/ 23 июня 2009

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

Итак, как мне легко определить, что папка была изменена?

Ответы [ 7 ]

4 голосов
/ 23 июня 2009

Я думаю, вам нужно будет проверить время модификации каталога и подкаталога (для добавляемых / удаляемых файлов) и время модификации файла (для изменений в каждом файле).

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

См. File.lastModified ()

РЕДАКТИРОВАТЬ: Поскольку я написал выше, Java 7 вышла с возможностью просмотра каталогов .

3 голосов
/ 23 июня 2009

Вот список возможных решений и пример простого File / Folder Watcher .

2 голосов
/ 23 июня 2009

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

JNA имеет образец для уведомления о смене кроссплатформенности здесь . Не уверен, как легко ты мог бы найти это.

1 голос
/ 23 июня 2009

Вам нужно смотреть каждый файл, отслеживать атрибут File.lastModified и проверять флаг File.exists вместе с небольшим количеством простой рекурсии для обхода структуры каталогов.

1 голос
/ 23 июня 2009

Я не знаю, хорошо ли это, но вот один человек взялся за проблему.

Похоже, в .NET есть что-то встроенное: FileSystemWatcher

ОБНОВЛЕНИЕ: Благодаря kd304 я только что узнал, что в Java 7 будет та же функция . Не принесет вам сегодня много пользы, если только вы не сможете использовать Preview Release .

0 голосов
/ 27 июня 2012

Да, существует несколько доступных слушателей для каталогов, но все они относительно сложны и в большинстве случаев используют потоки.

Несколько дней назад я закончил почти разгоряченную дискуссию с одним из наших инженеров о том, было ли допустимым создание нового потока (в веб-приложении) просто для мониторинга дерева каталогов. В конце концов я согласился с ним, но благодаря тому, что придумал что-то настолько быстрое, что иметь слушателя не нужно. Примечание: решение, описанное ниже, работает, только если вам не нужно знать , какой файл изменился, только тот файл a изменился.

Вы предоставляете следующему методу коллекцию файлов (например, полученную с помощью метода FileUtils.listFiles () Apache IO), и это возвращает хэш для коллекции. Если какой-либо файл добавлен, удален или дата его изменения изменилась, хэш изменится.

В моих тестах 50K-файлы занимали около 750 мс на коробке Linux с частотой 3 ГГц. Прикосновение к любому из файлов изменяет хеш. В моей собственной реализации я использую другой алгоритм хеширования (DJB), который немного быстрее, но в этом суть. Теперь мы просто храним хеш и проверяем каждый раз, как он довольно безболезненный, особенно для небольших коллекций файлов. Если что-то меняется, мы переиндексируем каталог. Сложность наблюдателя просто не стоила того в нашем приложении.

/**
 *  Provided a directory and a file extension, returns
 *  a hash using the Adler hash algorithm.
 *   
 * @param files  the Collection of Files to hash.
 * @return       a hash of the Collection.
 */
public static long getHash( Collection<File> files )
{
    Adler32 adler = new Adler32();
    StringBuilder sb = new StringBuilder();
    for ( File f : files ) {
        String s = f.getParent()+'/'+f.getName()+':'+String.valueOf(f.lastModified());
        adler.reset();
        adler.update(s.getBytes());
        sb.append(adler.getValue()+' ');
    }
    adler.reset();
    adler.update(sb.toString().getBytes());
    return adler.getValue();
}

И да, есть возможности для улучшения (например, мы используем метод хеширования, а не вставляем его). Вышесказанное урезано от нашего реального кода, но должно дать вам хорошее представление о том, что мы сделали.

0 голосов
/ 23 июня 2009

с NIO2 (Java7) это будет очень легко. С Java6 вы могли бы вызывать list () и сравнивать с предыдущим списком раз в секунду? (бедняга, наблюдающий за служением)

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