利用WatchService实现文件监视

Java.nio.file WatchService类图

  • FileSystem:当前系统默认的文件系统。
  • WatchService:文件系统监视服务的接口类,它的具体实现由监视服务提供者负责加载(不同的操作系统实现不同的加载类,如windows的WindowsWatchService类)。
  • Watchable:实现了Watchable接口的对象才能注册监视服务WatchService,由于Path类实现了Watchable接口,固可以通过Path类对文件目录进行监听。
  • WatchKey:该类代表着WatchService类和Watchable类的注册关系,WatchKey在Watchable对象(Path对象)向WatchService注册的时候被创建。

 

实现代码与解析

/*
* 创建所需要监控目录树的根目录File对象。
* */
File file = new File("/delete");
        
/*
* 转换成Path对象。
* */
Path parentPath = file.toPath();
/*
*创建监视服务类WatchService对象。
* */
WatchService watchService = FileSystems.getDefault().newWatchService();
        
/*
* 对根目录注册监听服务。
* 1.ENTRY_CREATE:创建条目时返回的事件类型
* 2.ENTRY_DELETE:删除条目时返回的事件类型
* 3.ENTRY_MODIFY:修改条目时返回的事件类型
* 4.OVERFLOW:表示事件丢失或被丢弃,不必要注册该事件类型
* */
parentPath.register(watchService
        , StandardWatchEventKinds.ENTRY_CREATE
        ,StandardWatchEventKinds.ENTRY_DELETE
        ,StandardWatchEventKinds.ENTRY_MODIFY);
/*
* -------遍历根目录及子目录,将其全都注册监听服务-------
* 创建链表结构存储File对象。
* 添加根目录的对象到链表尾。
* */
LinkedList<File> linkfile = new LinkedList<>();
linkfile.addLast(file);

/*
* 当链表还有File对象时进入循环。
* */
while(linkfile.size()>0){
/*
* 移除链表表头的File对象并返回给f
* 使用listFiles()方法生成File数组,
* 数组储存f代表目录中的File对象。
* */
   File f = linkfile.removeFirst();
   File[] files = f.listFiles();
   for (File f1:files
    ) {
/*
* 遍历数组中的每一个File对象。
* 判断其是不是目录,
* 如果是目录则将其添加到链表尾,
* 只有目录可以注册监听服务。
* */
   if(f1.isDirectory()){
      linkfile.addLast(f1);
                    
/*
* 给当前目录注册监听服务。
* */
f1.toPath().register(watchService
       , StandardWatchEventKinds.ENTRY_CREATE
       ,StandardWatchEventKinds.ENTRY_DELETE
       ,StandardWatchEventKinds.ENTRY_MODIFY);
         }
    }
}
/*
* 创建一个线程用来获取监听事件WatchEvent对象
* */
new Thread(()->{
    /*
    * 构建无限循环等待事件发生
    * */
    while(true){
        
        /*
        * 通过WatchService对象tack()方法产生WatchKey实例key
        * */
        WatchKey key = null;
        try {
            key = watchService.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        /*
        * WatchKey对象key轮询事件(pollEvents())获得事件队列
        * 遍历事件(WatchEvent)获得变化文件的信息
        * */
        for (WatchEvent event: key.pollEvents()
        ) {
            /*
            * event.context()返回Object类型,可转化为String和Path类型。
            * event.kind()返回事件种类。
            * */
            Path file2 = (Path)event.context();
            String str = file2.toFile().getAbsolutePath();
            System.out.println(str+" "+event.kind().toString());
        }
        /*
        * 重置WatchKey对象,使事件对象回到队列。
        * */
        key.reset();
    }
}).start();
/*
 * 测试代码,改变文件
 * */
new File("/delete/123.txt").createNewFile();
new File("/delete/create").mkdir();
new File("/delete/234.txt").delete();
new File("/delete/create/456.txt").createNewFile();
/*
* Output:
D:\专业\ideajava\CSDN\123.txt ENTRY_CREATE
D:\专业\ideajava\CSDN\create ENTRY_CREATE
D:\专业\ideajava\CSDN\234.txt ENTRY_MODIFY
D:\专业\ideajava\CSDN\234.txt ENTRY_DELETE
D:\专业\ideajava\CSDN\create ENTRY_MODIFY
* */

注意:

  • WatchService监听在系统支持的情况下采用事件驱动机制,可降档为扫描式机制。
  • 事件发生后需使用reset()方法重置WatchKey对象,否则事件所属的目录的改动通知只会发生一次。
posted @ 2018-12-13 22:27  问月晚安  阅读(2253)  评论(0编辑  收藏  举报