前言有时候你可能会有一个疑问,IDE总能检测到外部文件是否发生了变化,比如你在某个类中添加了一些代码,那么IDE会弹出一个框说你做了Change。或者某个文件夹中的文件发生了变化,比如新建一个或者删除一个等等,这时候我们的IDE还是可以检测到的。这个功能是如何实现的呢?本文主要研究NIO的其中一个类,叫做WatchService。还有一些其他的方式也可以轻松实现监控文件夹的功能,比如java轮询的方式,或者common-io的方式,我慢慢比较。OK,我们先来看一个简单的例子是如何实现的,接下来分析如何实现呢?一、代码实现1、简单案例这段代码非常简单,只需要四步:publicstaticvoidmain(String[]args)throwsException{//第一步:获取WatchServiceWatchServicewatchService=FileSystems.getDefault().newWatchService();//第二步:确定要监听的路径Pathpath=Paths.get("G:\\");//第三步:绑定这个路径设置WatchService,确定监听的事件path.register(watchService,StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY);WatchKeykey;//第四步:当有事件时,开始触发while((key=watchService.take())!=null){for(WatchEvent>event:key.pollEvents()){System.out.println("事件"+event.kind()+"发生,文件为:"+event.context());}key.reset();}}这里我们监控G盘,然后我们在G盘新建一个文件,然后删除修改,后台会打印相关信息。现在准备监控了,很简单。2、代码分析的第一步和第二步是新建一个获取WatchService的路径,获取要监听的路径。这很容易理解。第三步绑定,这里只需要注意两个重要的事情:首先,path以watchService为第一个参数,然后是StandardWatchEventKinds的可变参数。共有四种。StandardWatchEventKinds.ENTRY_CREATE-有新文件时触发。可能创建了一个新文件。StandardWatchEventKinds.ENTRY_MODIFY-修改文件时触发。所有文件编辑都会触发此事件。在某些平台上,即使更改文件属性也可以触发它。StandardWatchEventKinds.ENTRY_DELETE-在文件被删除、移动或重命名时触发。StandardWatchEventKinds.OVERFLOW—触发指示丢失或丢失的事件。第四步是持续监测。当watchService不为空时,开始获取对应的事件,弹出poll。最后还有一个reset返回对应的句柄,继续处理下一个事件。3.源码分析由于watchService是接口,所以分析起来比较简单。一共包含三个方法//方法一:关闭watchService@Overridevoidclose()throwsIOException;//方法二:弹出事件WatchKeypoll();//方法三:弹出WatchKeypoll带参数(longtimeout,TimeUnitunit)throwsInterruptedException;//方法四:获取事件。WatchKeytake()throwsInterruptedException;由于方法比较简单,我们直接看方法的注释即可。结论WatchService接口是在java7版本引入的。主要处理NIO文件相关的问题。但是WatchService其实也有很多缺点。WatchService正在扫描且效率低下。WatchService代码很难写。虽然上面看起来很简单,但是在实际开发中却很麻烦。WatchService无法监听多级目录,父文件夹需要提前存在。鉴于以上原因,简单实现上可以使用,但是有一个更强大的工具commons-io,使用起来更简单高效。下篇文章给出。
