java watch service_Java WatchService API 教程
在此示例中,我们将学习使用Java 8 WatchService API观察目录及其中的所有子目录和文件。
How to register Java 8 WatchService
要注册WatchService ,请获取目录路径并使用path.register()方法。
Path path = Paths.get(".");
WatchService watchService = path.getFileSystem().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
Watching for change events
要获取发生在目录和其中文件上的更改,请使用watchKey.pollEvents()方法,该方法以流的形式返回所有更改事件的集合。WatchKey watchKey = null;
while (true) {
watchKey = watchService.poll(10, TimeUnit.MINUTES);
if(watchKey != null) {
watchKey.pollEvents().stream().forEach(event -> System.out.println(event.context()));
}
watchKey.reset();
}
该密钥一直有效,直到:通过调用其cancel方法显式地取消它,或者
隐式取消,因为该对象不再可访问,或者
通过关闭手表服务。
如果要在循环中多次使用同一键来多次获取更改事件,请不要忘记调用watchKey.reset()方法,该方法watchKey.reset()键再次设置为ready状态。请注意,诸如如何检测事件,其及时性以及是否保留其顺序之类的几件事高度依赖于底层操作系统。 某些更改可能导致一个操作系统中的单个条目,而类似的更改可能导致另一操作系统中的多个事件。
Watch Directory, Sub-directories and Files for Changes Example
在此示例中,我们将看到一个观看目录的示例,该目录中包含所有子目录和文件。 我们将维护监视键和目录Map keys以正确识别已修改的目录。
下面的方法将向观察者注册一个目录,然后将目录和密钥存储在地图中。
private void registerDirectory(Path dir) throws IOException
{
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
}
在遍历目录结构并为遇到的每个目录调用此方法时,将递归调用此方法。private void walkAndRegisterDirectories(final Path start) throws IOException {
// register directory and sub-directories
Files.walkFileTree(start, new SimpleFileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
registerDirectory(dir);
return FileVisitResult.CONTINUE;
}
});
}
请注意,无论何时创建新目录,我们都会在watchservice中注册该目录,并将新密钥添加到地图中。WatchEvent.Kind kind = event.kind();
if (kind == ENTRY_CREATE) {
try {
if (Files.isDirectory(child)) {
walkAndRegisterDirectories(child);
}
} catch (IOException x) {
// do something useful
}
}
将以上所有内容与处理事件的逻辑放在一起,完整的示例如下所示:package com.howtodoinjava.examples;
import static java.nio.file.StandardWatchEventKinds.*;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
public class Java8WatchServiceExample {
private final WatchService watcher;
private final Map keys;
/**
* Creates a WatchService and registers the given directory
*/
Java8WatchServiceExample(Path dir) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap();
walkAndRegisterDirectories(dir);
}
/**
* Register the given directory with the WatchService; This function will be called by FileVisitor
*/
private void registerDirectory(Path dir) throws IOException
{
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
}
/**
* Register the given directory, and all its sub-directories, with the WatchService.
*/
private void walkAndRegisterDirectories(final Path start) throws IOException {
// register directory and sub-directories
Files.walkFileTree(start, new SimpleFileVisitor() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
registerDirectory(dir);
return FileVisitResult.CONTINUE;
}
});
}
/**
* Process all events for keys queued to the watcher
*/
void processEvents() {
for (;;) {
// wait for key to be signalled
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
Path dir = keys.get(key);
if (dir == null) {
System.err.println("WatchKey not recognized!!");
continue;
}
for (WatchEvent> event : key.pollEvents()) {
@SuppressWarnings("rawtypes")
WatchEvent.Kind kind = event.kind();
// Context for directory entry event is the file name of entry
@SuppressWarnings("unchecked")
Path name = ((WatchEvent)event).context();
Path child = dir.resolve(name);
// print out event
System.out.format("%s: %s\n", event.kind().name(), child);
// if directory is created, and watching recursively, then register it and its sub-directories
if (kind == ENTRY_CREATE) {
try {
if (Files.isDirectory(child)) {
walkAndRegisterDirectories(child);
}
} catch (IOException x) {
// do something useful
}
}
}
// reset key and remove from set if directory no longer accessible
boolean valid = key.reset();
if (!valid) {
keys.remove(key);
// all directories are inaccessible
if (keys.isEmpty()) {
break;
}
}
}
}
public static void main(String[] args) throws IOException {
Path dir = Paths.get("c:/temp");
new Java8WatchServiceExample(dir).processEvents();
}
}
运行该程序并在给定输入中更改文件和目录后,您将在控制台中注意到捕获的事件。Output:
ENTRY_CREATE: c:\temp\New folder
ENTRY_DELETE: c:\temp\New folder
ENTRY_CREATE: c:\temp\data
ENTRY_CREATE: c:\temp\data\New Text Document.txt
ENTRY_MODIFY: c:\temp\data
ENTRY_DELETE: c:\temp\data\New Text Document.txt
ENTRY_CREATE: c:\temp\data\tempFile.txt
ENTRY_MODIFY: c:\temp\data
ENTRY_MODIFY: c:\temp\data\tempFile.txt
ENTRY_MODIFY: c:\temp\data\tempFile.txt
ENTRY_MODIFY: c:\temp\data\tempFile.txt
这就是使用Java 8 WatchService API监视文件更改并进行处理的简单示例。
Resources: