NIO 之 WatchService

NIO 之 WatchService

Java 1.6版本之前是不存在目录监控的API的。若是要实现这种功能必需要本身遍历目录,记录各个文件的状况,而后定时所有遍历一次,从 JDK7 以后出现了 WatchService 类,实现了对目录下文件的监控。java

总体流程

整个监控目录文件操做的流程大体以下:操作系统

  1. 获取 WatchService
  2. 注册指定目录的监视器 WatchService
  3. 等待目录下的文件发生变化
  4. 对发生变化的文件进行操做

获取 WatchService 实例

WatchService 类的实现其实是对操做系统的文件监视器的封装,相比以前的手动实现,优雅了很多。由于不须要遍历文件总体而言效率也高不少。如下为获取 WatchService 实例的代码,经过 FileSystem.getDefault() 可看出并不是是本身实现的。从 newWatchService() 方法名看, WatchService 能够获取多个。.net

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

实际上调用此方法后,程序会新开一个线程,监视文件变化发出的信号,此时线程还没有就绪。线程

为目录注册监视器

有了监视器,接下来咱们须要注册监视器了。code

Path path = Paths.get("src");
WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

注册监视器须要用到 Path 实例,该实例对应的必须是一个目录,不容许是一个文件。
方法比较简单,就是说为目录注册一个监视器,监视目录下文件的变化。
关于 StandardWatchEventKinds.ENTRY_MODIFY ,表示监视文件的修改事件,它是 WatchEvent.Kind<?> 的实现类。
看起来它像是枚举,实际上它并非。JDK 中帮咱们定义了三种事件,新增、修改和删除。orm

获取目录下的变化

获取目录的变化须要使用 WatchServicetake() 方法或 poll() 方法。对象

WatchKey key = watchService.take();
WatchKey pollKey = watchService.poll();

take() 是一个阻塞方法,会等待监视器发出的信号才返回。
poll() 是一个非阻塞方法,会当即返回当时监视器中是否有信号。
返回的 WatchKey 对象,其实是一个单例,和以前 path.register() 方法返回的实例是同一个。它只能保存某一时间点的文件变化信息。blog

处理文件变化事件

List<WatchEvent<?>> events = key.pollEvents();
for (WatchEvent<?> pollEvent : events) {
    Object o = pollEvent.context();
    WatchEvent.Kind kind = pollEvent.kind();
}

key.reset();

pollEvents() 用于获取文件变化事件,只能获取一次,不能重复获取,相似队列的形式。
context() 返回触发该事件的那个文件或目录的路径(相对路径)
kind() 返回事件类型(ENTRY_CREATE、ENTRY_DELETE、ENTRY_MODIFY之一)
reset() 每次调用 WatchService 的 take() 或 poll() 方法时须要经过本方法重置。队列

一个简单的例子

public void watchServiceExample() throws IOException, InterruptedException {
    WatchService watchService = FileSystems.getDefault().newWatchService();

    Path path = Paths.get("D:/code");

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

    while (true) {
        // 尝试获取下一个变化信息的监控池,若是没有变化则一直等待
        WatchKey key = watchService.take();

        for (WatchEvent<?> pollEvent : key.pollEvents()) {
            System.out.println(String.format("%s is %s.", pollEvent.context().toString(), pollEvent.kind().name().substring(6)));
        }

        if (!key.reset()) {
            break;
        }
    }
}

总结

WatchService 的优势就不用多说了,这里就说一个缺点: 只能监视当前目录下的文件和目录,不能监视子目录事件


参考

[疯狂Java]NIO.2:WatchService、WatchKey(监控文件变化)

本文若有问题,欢迎在评论区中指正。

相关文章
相关标签/搜索