转自:https://my.oschina.net/liufukin/blog/2222487
1、简介
java程序监控文件夹的变化可以使用“定时循环递归”的方式进行扫描,但是性能非常低。
除此之外,可以借助于操作系统的文件系统的事件驱动方式进行处理也就是文件系统有变化就会通知到java程序,既然需要操作系统的支持,就要有对应的dll文件才可以,目前已经有一款开源的框架jnotify,通过它就可以实现此功能。
2、代码
-
1、maven依赖
<!-- https://mvnrepository.com/artifact/jnotify/jnotify --> <dependency> <groupId>jnotify</groupId> <artifactId>jnotify</artifactId> <version>0.94</version> </dependency>
-
2、代码
import net.contentobjects.jnotify.JNotify; import net.contentobjects.jnotify.JNotifyException; import net.contentobjects.jnotify.JNotifyListener; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.PrintWriter; import java.util.concurrent.atomic.AtomicInteger; /** * 利用jnotify来实现监听文件夹及文件变化 * 这样就避免了不断递归扫描的问题 * * [@Author](https://my.oschina.net/arthor) liufu * [@E-mail](https://my.oschina.net/rosolio): [email protected] * @CreateTime 2018/9/17 16:24 */ public class JnotifyTest { public static void main(String[] args) throws InterruptedException, JNotifyException { // 打印lib路径, 看看在哪里设置jnotify比较合适 System.out.println(System.getProperty("java.library.path")); // 设置监听的文件夹,或者文件 String linstenerPath = "E:\\testPath"; // 指定监听的模式,创建、删除、修改、和重命名 int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED; // 是否监控子目录 boolean watchSubtree = true; // 设置监听器,得到一个监听器id,可以通过这个id来移除监听器 int watchId = JNotify.addWatch(linstenerPath, mask, watchSubtree, new MyJnotifyListner()); // 如果需要去掉监听器,比如不需要监听某个目录了 //JNotify.removeWatch(watchId); //启动线程,不断的创建、重命名和删除文件,测试jnotify的响应速度 new DynamicBuildFile(linstenerPath).start(); // 一定要让程序等待,只要程序不退出,那么上面的监听器就一直有效 Thread.sleep(Integer.MAX_VALUE); } static class MyJnotifyListner implements JNotifyListener { AtomicInteger integer = new AtomicInteger(0); [@Override](https://my.oschina.net/u/1162528) public void fileCreated(int i, String rootPath, String name) { System.out.println("create a file : " + rootPath + "/" + name + ";integer:" + integer.incrementAndGet()); } @Override public void fileDeleted(int i, String rootPath, String name) { System.out.println("delete a file : " + rootPath + "/" + name + ";integer:" + integer.incrementAndGet()); } @Override public void fileModified(int i, String rootPath, String name) { System.out.println("modified a file : " + rootPath + "/" + name + ";integer:" + integer.incrementAndGet()); } @Override public void fileRenamed(int i, String rootPath, String oldName, String newName) { System.out.println("rename a file, oldName : " + (rootPath + "/" + oldName) + ";newName : " + (rootPath + "/" + newName) + "integer:" + integer.incrementAndGet()); } } /** * 动态生成和删除文件,测试jnotify的响应速度 * 总结 * 1、create 只会触发create * 2、delete 会触发 delete和modified * 3、rename 会出发一次rename 和modified * 4、如果编辑那个文件,那么会先产生一个临时文件(create),然后modified,在然后rename */ static class DynamicBuildFile extends Thread { String basePath; DynamicBuildFile(String basePath) { this.basePath = basePath; } @Override public void run() { while (true) { File file1 = new File(basePath + "\\aa1.txt"); File file2 = new File(basePath + "\\aa2.txt"); File file3 = new File(basePath + "\\aa3.txt"); try { PrintWriter printWriter1 = new PrintWriter(new FileOutputStream(file1)); //下面两行,都会触发modify printWriter1.println("dddd"); printWriter1.close(); PrintWriter printWriter2 = new PrintWriter(new FileOutputStream(file2)); printWriter2.println("dddd"); printWriter2.close(); PrintWriter printWriter3 = new PrintWriter(new FileOutputStream(file3)); printWriter3.println("dddd"); printWriter3.close(); file1.delete(); file2.delete(); file3.delete(); } catch (FileNotFoundException e) { e.printStackTrace(); } } } } }