nio主要是通过WatchService、Watchkey和Path来实现文件的监控;
public class FileMonitor {
private WatchService watcher;
public FileMonitor(String directory) throws IOException {
watcher = FileSystems.getDefault().newWatchService();
Path path = Paths.get(directory);
path.register(watcher, ENTRY_CREATE, ENTRY_MODIFY,ENTRY_DELETE);
}
@SuppressWarnings("InfiniteLoopStatement")
public void watchFile() throws InterruptedException{
while (true) {
WatchKey key = watcher.take();
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent.Kind<?> kind = event.kind();
if (kind.equals(ENTRY_CREATE)) {
System.out.println("新文件");
} else if (kind.equals(ENTRY_MODIFY)) {
System.out.println("修改文件");
} else if (kind.equals(ENTRY_DELETE)) {
System.out.println("删除文件");
} else if (kind.equals(OVERFLOW)) {
System.out.println("文件操作遗失");
} else {
System.out.println("不能识别的文件操作");
}
Path fileName = (Path) event.context();
System.out.printf("发现 %s 操作,文件为 %s%n", kind.name(), fileName);
}
if(!key.reset()){
break;
}
}
}
}
Path接口中有一个register方法,第一个参数,指定了要注册到哪个监控服务,第二个参数表示要监控的文件操作类型
WatchKey register(WatchService watcher,
WatchEvent.Kind<?>... events)
throws IOException;
监控类型存储在 StandardWatchEventKinds
中,主要有以下类型:
OVERFLOW
表示一个特殊事件已丢失或遗弃ENTRY_CREATE
表示文件创建ENTRY_DELETE
表示文件删除ENTRY_MODIFY
表示文件修改WatchService
的实现类 AbstractWatchService
中存储了这个监控服务监控的对象信息。
在这个类中,可以移除、新增、关闭监控服务。
而被监控的对象中又存储了自己被监控到哪个服务,使用了设计模式中的观察者模式。
通过这几个核心的类就可以实现监控啦。
调用监控方法后,必须要调用 WatchKey
的reset方法,因为watchkey有两个状态
监控到事件后,会被移除监控队列,状态会被为SIGNALLED,需要调用reset方法重置状态为READY,让监控对象重新进入监控队列;
监控到文件改变:
重置:
代码中调用reset方法后,会验证是否正常,所以要在自己的代码里做判断,如果返回不正常,则需要做处理,我的代码里只是做了一个简单的break,可以根据自己的需求自己处理