Spec-Zone .ru
спецификации, руководства, описания, API
|
Вы когда-либо редактировали файл, используя IDE или другого редактора, и диалоговое окно, кажется, сообщает Вам, что один из открытых файлов изменился на файловой системе и должен быть перезагружен? Или возможно, как IDE NetBeans, приложение только спокойно обновляет файл, не уведомляя Вас. Следующее демонстрационное диалоговое окно показывает, как это уведомление смотрит со свободным редактором, jEdit:
Чтобы реализовать эту функциональность, названную уведомлением об изменении файла, программа должна быть в состоянии обнаружить то, что происходит с соответствующим каталогом на файловой системе. Один способ сделать так состоит в том, чтобы опросить файловую систему, ища изменения, но этот подход неэффективен. Это не масштабируется к приложениям, у которых есть сотни открытых файлов или каталогов, чтобы контролировать.
java.nio.file
пакет обеспечивает API уведомления об изменении файла, названный API Службы Часов. Этот API позволяет Вам зарегистрировать каталог (или каталоги) со службой часов. Регистрируясь, Вы говорите службу, какими типами событий Вы интересуетесь: создание файла, удаление файла, или модификация файла. Когда служба обнаруживает мероприятие, она передается зарегистрированному процессу. У зарегистрированного процесса есть поток (или пул потоков) выделенный наблюдению за любыми событиями, для которых это зарегистрировалось. Когда событие входит, оно обрабатывается как необходимый.
Этот раздел покрывает следующее:
WatchService
API является довольно низким уровнем, разрешая Вам настроить это. Можно использовать это как есть, или можно хотеть создавать высокоуровневый API сверху этого механизма так, чтобы это подошло для Ваших определенных потребностей.
Вот основные шаги, требуемые реализовывать службу часов:
WatchService
"наблюдатель" для файловой системы.WatchKey
экземпляр для каждого каталога, который Вы регистрируете.closed
метод).WatchKeys
ориентированы на многопотоковое исполнение и может использоваться с java.nio.concurrent
пакет. Можно выделить
Поскольку этот API более совершенствуется, испытайте его перед продолжением. Сохраните
пример к Вашему компьютеру, и компиляция это. Создайте a WatchDir
test
каталог, который передадут к примеру. WatchDir
использует единственный поток, чтобы обработать все события, таким образом, он блокирует ввод с клавиатуры, ожидая событий. Или выполните программу в отдельном окне, или в фоновом режиме, следующим образом:
java WatchDir test &
Игра с созданием, удалением, и редактированием файлов в test
каталог. Когда любое из этих событий имеет место, сообщение печатается к консоли. Когда Вы закончили, удалите test
каталог и WatchDir
выходы. Или, если Вы предпочитаете, можно вручную уничтожить процесс.
Можно также наблюдать все дерево файла, определяя -r
опция. Когда Вы определяете -r
, WatchDir
обходит дерево файла, регистрируя каждый каталог в службе часов.
Первый шаг должен создать новое WatchService
при использовании newWatchService
FileSystem
class, следующим образом:
WatchService watcher = FileSystems.getDefault().newWatchService();
Затем, зарегистрируйте один или более объектов в службе часов. Любой объект, который реализует Watchable
Path
class реализует Watchable
интерфейс, таким образом, каждый каталог, который будет контролироваться, регистрируется как a Path
объект.
Как с любым Watchable
, Path
class реализует два register
методы. Эта страница использует версию с двумя параметрами, register(WatchService, WatchEvent.Kind<?>...)
WatchEvent.Modifier
, который в настоящий момент не реализуется.)
Регистрируя объект в службе часов, Вы определяете типы событий, которых Вы хотите следить за развитием. Поддерживаемый StandardWatchEventKinds
ENTRY_CREATE
– Запись в каталоге создается.ENTRY_DELETE
– Запись в каталоге удаляется.ENTRY_MODIFY
– Запись в каталоге изменяется.OVERFLOW
– Указывает, что события, возможно, были потеряны или отброшены. Вы не должны зарегистрироваться для OVERFLOW
событие, чтобы получить это.Следующий фрагмент кода показывает, как зарегистрировать a Path
экземпляр для всех трех типов события:
import static java.nio.file.StandardWatchEventKinds.*; Path dir = ...; try { WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); } catch (IOException x) { System.err.println(x); }
Порядок событий в цикле обработки событий следует:
poll
null
значение, если недоступный.poll(long, TimeUnit)
TimeUnit
параметр определяет, является ли требуемое время наносекундами, миллисекундами, или некоторой другой единицей времени.take
List
из WatchEvents
pollEvents
kind
OVERFLOW
событие. Можно хотеть обрабатывать переполнение или игнорировать его, но следует протестировать на него.context
ready
состояние, вызывая reset
false
, ключ больше не действителен, и цикл может выйти. Этот шаг очень важен. Если Вы не в состоянии вызвать reset
, этот ключ не будет получать дальнейшие события.У ключа часов есть состояние. В любой момент времени его состояние могло бы быть одним из следующего:
Ready
указывает, что ключ готов принять события. Когда сначала создающийся, ключ находится в состоянии готовности.Signaled
указывает, что одно или более событий ставятся в очередь. Как только ключ был сообщен, это больше не находится в состоянии готовности до reset
Invalid
указывает, что ключ больше не является активным. Это состояние происходит, когда одно из следующих событий имеет место: cancel
Вот пример цикла обработки событий. Это берется от
пример, который наблюдает каталог, ожидающий новых файлов, чтобы появиться. Когда новый файл становится доступным, он исследуется, чтобы определить, является ли это a Email
text/plain
файл при использовании probeContentType(Path)
text/plain
файлы будут посланы по электронной почте к псевдониму, но ту деталь реализации оставляют читателю.
Методы, определенные для API службы часов, показывают полужирным:
for (;;) { // wait for key to be signaled WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return; } for (WatchEvent<?> event: key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); // This key is registered only // for ENTRY_CREATE events, // but an OVERFLOW event can // occur regardless if events // are lost or discarded. if (kind == OVERFLOW) { continue; } // The filename is the // context of the event. WatchEvent<Path> ev = (WatchEvent<Path>)event; Path filename = ev.context(); // Verify that the new // file is a text file. try { // Resolve the filename against the directory. // If the filename is "test" and the directory is "foo", // the resolved name is "test/foo". Path child = dir.resolve(filename); if (!Files.probeContentType(child).equals("text/plain")) { System.err.format("New file '%s'" + " is not a plain text file.%n", filename); continue; } } catch (IOException x) { System.err.println(x); continue; } // Email the file to the // specified email alias. System.out.format("Emailing file %s%n", filename); //Details left to reader.... } // Reset the key -- this step is critical if you want to // receive further watch events. If the key is no longer valid, // the directory is inaccessible so exit the loop. boolean valid = key.reset(); if (!valid) { break; } }
Имя файла получается от контекста события.
пример получает имя файла с этим кодом:Email
WatchEvent<Path> ev = (WatchEvent<Path>)event; Path filename = ev.context();
Когда Вы компилируете Email
пример, это генерирует следующую ошибку:
Note: Email.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
Эта ошибка является результатом строки кода, который бросает WatchEvent<T>
к a WatchEvent<Path>
.
пример избегает этой ошибки, создавая утилиту WatchDir
cast
метод, который подавляет предупреждение непроверенное, следующим образом:
@SuppressWarnings("unchecked") static <T> WatchEvent<T> cast(WatchEvent<?> event) { return (WatchEvent<Path>)event; }
Если Вы незнакомы с @SuppressWarnings
синтаксис, см. Аннотации.
API Службы Часов разрабатывается для приложений, которые должны быть уведомлены о событиях изменения файла. Это хорошо подходит для любого приложения, как редактор или IDE, который потенциально имеет много открытых файлов и должен гарантировать, что файлы синхронизируются с файловой системой. Это также хорошо подходит для сервера приложений, который наблюдает каталог, возможно ожидающий .jsp
или .jar
файлы, чтобы отбросить, чтобы развернуть их.
Этот API не разрабатывается для того, чтобы индексировать жесткий диск. У большинства реализаций файловой системы есть собственная поддержка уведомления об изменении файла. API Службы Часов использует в своих интересах эту поддержку где доступный. Однако, когда файловая система не поддерживает этот механизм, Служба Часов опросит файловую систему, ожидающую событий.