Рубрики
Без рубрики

Руководство по watchService на Java NIO2

Быстрое и практичное руководство по Java NIO2 WatchService

Автор оригинала: baeldung.

1. Обзор

В этой статье мы собираемся изучить WatchService интерфейс API файловой системы Java NIO.2. Это одна из менее известных особенностей новых API-кодов, которые были введены в Java 7 наряду с FileVisitor интерфейс.

Использовать WatchService интерфейс в приложениях, вам нужно импортировать соответствующие классы:

import java.nio.file.*;

2. Зачем использовать WatchService

Распространенным примером для понимания того, что делает служба, является IDE.

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

Аналогичным образом, новые фреймворки, такие как Play, также по умолчанию перезаряжают код приложения – всякий раз, когда вы выполняете правки от любого редактора.

В этих приложениях используется функция под названием файл изменения уведомления которая доступна во всех файловых системах.

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

На Java 7 NIO.2 WatchService API предоставляет масштабируемое решение для мониторинга каталогов изменений. Он имеет чистый API и настолько хорошо оптимизирован для производительности, что нам не нужно реализовывать наше собственное решение.

3. Как работает вахтовая служба?

Использовать WatchService функции, первый шаг заключается в создании WatchService например, с помощью java.nio.file.FileSystems класс:

WatchService watchService = FileSystems.getDefault().newWatchService();

Далее мы должны создать путь к каталогу, который мы хотим контролировать:

Path path = Paths.get("pathToDir");

После этого шага мы должны зарегистрировать путь с помощью часовой службы. На данном этапе необходимо понять две важные концепции. StandardWatchEventKinds класс и WatchKey класс. Взгляните на следующий код регистрации только для того, чтобы понять, где каждую осень. Мы будем следовать этому с объяснениями того же:

WatchKey watchKey = path.register(
  watchService, StandardWatchEventKinds...);

Обратите внимание только на две важные вещи здесь: Во-первых, вызов API регистрации пути принимает экземпляр службы часов в качестве первого параметра, за которым следуют переменные аргументы StandardWatchEventKinds . Во-вторых, тип возврата процесса регистрации является WatchKey пример.

3.1. СтандартныеWatchEventKinds

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

  • StandardWatchEventKinds.ENTRY_CREATE – срабатывает, когда новая запись сделана в смотрел каталог. Это может быть связано с созданием нового файла или переименованием существующего файла.
  • StandardWatchEventKinds.ENTRY_MODIFY – срабатывает при изменению существующей записи в просмотренном каталоге. Все изменения файлов вызывают это событие. На некоторых платформах даже изменение атрибутов файлов вызовет его.
  • StandardWatchEventKinds.ENTRY_DELETE – срабатывает при удалении, перемещении или переименовании записи в каталоге просмотра.
  • StandardWatchEventKinds.OVERFLOW – срабатывает для обозначения потерянных или отброшенных событий. Мы не будем много внимания на нем

3.2. WatchKey

Этот класс представляет собой регистрацию каталога с часовой службой. Его экземпляр возвращается к нам часовой службой, когда мы регистрируем каталог, и когда мы просим часовую службу, если какие-либо события, которые мы зарегистрировали имели место.

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

Мы можем использовать опрос API:

WatchKey watchKey = watchService.poll();

Этот вызов API возвращается сразу. Он возвращает следующий ключ в очереди, любой из событий которого произошел, или null, если зарегистрированных событий не произошло.

Мы также можем использовать перегруженную версию, которая занимает тайм-аут аргумент:

WatchKey watchKey = watchService.poll(long timeout, TimeUnit units);

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

Наконец, мы можем использовать взять API:

WatchKey watchKey = watchService.take();

Этот последний подход просто блокируется до тех пор, пока событие не произойдет.

Здесь мы должны отметить кое-что очень важное: когда WatchKey экземпляр возвращается любой из опрос или взять API, он не будет захватывать больше событий, если он сброс API не вызывается:

watchKey.reset();

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

Наиболее практичное применение службы наблюдателей потребует цикла, в рамках которого мы постоянно проверяем изменения в каталоге и процессе просмотра соответственно. Мы можем использовать следующую идиому для реализации этого:

WatchKey key;
while ((key = watchService.take()) != null) {
    for (WatchEvent event : key.pollEvents()) {
        //process
    }
    key.reset();
}

Мы создаем часовой ключ для хранения значения возврата операции опроса. В то время как цикл будет блокировать до тех пор, пока условное заявление возвращается либо с ключом часов или нулевой.

Когда мы получаем клавишу часов, то в то время как цикл выполняет код внутри него. Мы используем СмотретьKey.pollEvents API для возврата списка событий, которые произошли. Затем мы используем для каждого цикл для обработки их один за другим.

После того, как все события будут обработаны, мы должны позвонить сбросить API, чтобы заведать ключ от часов снова.

4. Пример просмотра каталогов

Так как мы рассмотрели WatchService API в предыдущем подразделе и как он работает внутри страны, а также как мы можем использовать его, теперь мы можем пойти дальше и посмотреть на полный и практический пример.

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

Код содержит только несколько строк кода, поэтому мы просто будем держать его в основном методе:

public class DirectoryWatcherExample {

    public static void main(String[] args) {
        WatchService watchService
          = FileSystems.getDefault().newWatchService();

        Path path = Paths.get(System.getProperty("user.home"));

        path.register(
          watchService, 
            StandardWatchEventKinds.ENTRY_CREATE, 
              StandardWatchEventKinds.ENTRY_DELETE, 
                StandardWatchEventKinds.ENTRY_MODIFY);

        WatchKey key;
        while ((key = watchService.take()) != null) {
            for (WatchEvent event : key.pollEvents()) {
                System.out.println(
                  "Event kind:" + event.kind() 
                    + ". File affected: " + event.context() + ".");
            }
            key.reset();
        }
    }
}

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

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

Например, если вы идете к пользователю домой, нажмите правой кнопкой мыши в пространстве, выберите ‘ новый – > файл’ создать новый файл, а затем назвать его testFile . Затем вы добавляете содержимое и экономите. Выход на консоли будет выглядеть так:

Event kind:ENTRY_CREATE. File affected: New Text Document.txt.
Event kind:ENTRY_DELETE. File affected: New Text Document.txt.
Event kind:ENTRY_CREATE. File affected: testFile.txt.
Event kind:ENTRY_MODIFY. File affected: testFile.txt.
Event kind:ENTRY_MODIFY. File affected: testFile.txt.

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

5. Заключение

В этой статье мы изучили некоторые из менее часто используемых функций, доступных в API Java 7 NIO.2 – файлосистемы, в частности WatchService интерфейс.

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

И, как всегда, полный исходный код для примеров, используемых в этой статье, доступен в Проект Github .