Java监听文件WatchService的简单使用

public interface WatchService
extends Closeable

通过调用其register方法向监视服务注册Watchable对象,返回WatchKey以表示注册。 当检测到对象的事件时,将发信号通知密钥,如果当前未发出信号,则将其排队到监视服务,以便调用poll或take方法的消费者检索密钥并处理事件。 一旦处理了事件,消费者就会调用密钥的reset方法来重置密钥,该密钥允许密钥发出信号并随后用其他事件重新排队。

入门案例:

/**
 * 文件监听
 */
public class WatchServiceDemo implements Runnable{

    public static void main(String[] args) {
        WatchServiceDemo watchServiceDemo = new WatchServiceDemo();
        watchServiceDemo.run();

    }
    @Override
    public void run() {
        String path = "F:\\TestFile";
        WatchService watchService;
            try {
                //WatchService 实例化
                watchService = FileSystems.getDefault().newWatchService();
                //遍历文件
                Files.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path>(){
                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                        //这里监听文件的创建、修改、删除
                        dir.register(watchService,
                                StandardWatchEventKinds.ENTRY_DELETE,
                                StandardWatchEventKinds.ENTRY_CREATE,
                                StandardWatchEventKinds.ENTRY_MODIFY,
                                StandardWatchEventKinds.OVERFLOW);

                        return FileVisitResult.CONTINUE;
                    }
                });

                while (true) {
                WatchKey key = watchService.take();
                for (WatchEvent<?> watchEvent : key.pollEvents()) {
                    WatchEvent.Kind<?> kind = watchEvent.kind();
                    System.out.println("kind=="+kind);
                    if (kind.equals(StandardWatchEventKinds.OVERFLOW)){
                        System.out.println("file overflow...");

                    }
                    if (kind.equals(StandardWatchEventKinds.ENTRY_DELETE)){
                        System.out.println("file delete...");

                    }
                    if (kind.equals(StandardWatchEventKinds.ENTRY_MODIFY)){
                        System.out.println("file modify...");

                    }
                    if (kind.equals(StandardWatchEventKinds.ENTRY_CREATE)){
                        System.out.println("file create...");

                    }

                    WatchEvent<Path> watchEventPath= (WatchEvent<Path>)watchEvent;
                    //获取文件目录
                    Path filePath =  (Path) key.watchable();
                    //获取文件名
                    Path fileName = watchEventPath.context();
                    System.out.println("filePath=="+filePath+" fileName=="+fileName);

                }
                    boolean reset = key.reset();
                    System.out.println("reset==="+reset);

                }

        }catch (Exception e){
                e.printStackTrace();
            }
    }
}

WatchService实例化

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

将Path注册到WatchService中

dir.register(watchService,
           StandardWatchEventKinds.ENTRY_DELETE,
           StandardWatchEventKinds.ENTRY_CREATE,
           StandardWatchEventKinds.ENTRY_MODIFY,
           StandardWatchEventKinds.OVERFLOW);
  • StandardWatchEventKinds.OVERFLOW:事件丢失或失去
  • StandardWatchEventKinds.ENTRY_CREATE:目录内实体创建或本目录重命名
  • StandardWatchEventKinds.ENTRY_MODIFY:目录内实体修改
  • StandardWatchEventKinds.ENTRY_DELETE:目录内实体删除或重命名

WatchKey:该文件节点所绑定的监控信息池,当文件发生变化时所有的变化都会被导入监控池。监控池是静态的,只有当你主动去获取新的监控池时才会有更新的内容加入监控池。这就造成了系统接收到监控信息事件可能稍长的问题。

//获取下一个变化信息的监控池,如果没有变化就一直等待
WatchKey key = watchService.take();
//利用key.pollEvents()方法返回一系列的事件列表 WatchEvent<?> watchEvent
 for (WatchEvent<?> watchEvent : key.pollEvents()) {
 					//得到 监听的事件类型
                    WatchEvent.Kind<?> kind = watchEvent.kind();
                    System.out.println("kind=="+kind);
                    if (kind.equals(StandardWatchEventKinds.OVERFLOW)){
                        System.out.println("file overflow...");

                    }
                }
 WatchEvent<Path> watchEventPath= (WatchEvent<Path>)watchEvent;
                    //获取文件目录
                    Path filePath =  (Path) key.watchable();
                    //获取文件名
                    Path fileName = watchEventPath.context();

每次的到新的事件后,需要重置监听池

key.reset();

key.reset() 方法
每次take()或者poll()操作都会导致线程监控阻塞,每次操作文件可能需要长时间,如果监听目录下有其他事件发生,将会导致事件丢失。重置操作表示重启该线程,后续的事件都会被读到。

key.cancel()方法:关闭监听池服务

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值