java实现文件实时监控:Jnotify和FileAlteration

2017-07-25

来源:http://blog.csdn.net/qqchaozai/article/details/41282031

一、实时监控使用场景

(a)实时刷新文件缓存,比如页面图片
(b)实时刷新工程配置文件
(c)实时同步文件到镜像路径,比如与rsync结合,实现跨平台实时同步
二、Jnotify
官网地址:Jnotify

JNotify is a Java library that allow java application to listen to file system events, such as:File created;File modified;File renamed;File deleted

它能让Java程序监听文件系统的事件,如:文件(夹)创建,文件(夹)修改,文件(夹)重命名,文件(夹)删除。

支持Linux/Windows/MacOS,由于使用JNI调用了本地库所以支持的的并不完美。

Win下使用:要在java.library.path下加入依赖的dll (jnotify.dll/jnotify_64bit.dll)。

linux下使用:要在java.library.path下加入依赖的so(libjnotify.so)。

特别说明:

0.94版:仅仅支持GLIBC库版本在2.1.2之上的,它的实现基于inotify本地库。32位,64位都支持。

0.93版:支持GLIBC库版本在2.1.2之下的,但仅仅支持32位,64位的so库为提供。0.92同0.93。

所以Jnotify还无法跨平台。但是使用起来还是很简单的。

看代码,代码注释有详细的说明:

[java] view plain copy

  1. public class JnotifyTest {
  2.     public static void main(String[] args) {
  3.         try {
  4.             new JnotifyTest().test();
  5.         } catch (Exception e) {
  6.             e.printStackTrace();
  7.         }
  8.     }
  9.     public void test() throws Exception {
  10.         //监控路径
  11.         String path = “E:\\test\\rsync\\base”;
  12.         //可随意组合监听事件类型
  13.         int mask = JNotify.FILE_CREATED | JNotify.FILE_DELETED
  14.                 | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED;
  15.         //是否监控子目录
  16.         boolean watchSubtree = false;
  17.         //添加监听,返回监听唯一标示
  18.         int watchID = JNotify.addWatch(path, mask, watchSubtree, new Listener());
  19.         System.out.println(watchID);
  20.         //为啥睡眠?如果不睡眠,程序运行结束,监听就被移除 (Common-io的FileAlterationMonitor会继续运行不休眠)
  21.         Thread.sleep(1000000);
  22.         //根据watchID手动移除监听
  23.         boolean res = JNotify.removeWatch(watchID);
  24.         if (!res) {
  25.             //返回FALSE,监听标识无效
  26.         }
  27.     }
  28.     //可以在下面的监控方法中添加自己的代码。比如在fileModified中添加重新加载配置文件的代码
  29.     //可以结合rsync,实现实时同步文件
  30.     class Listener implements JNotifyListener {
  31.         public void fileRenamed(int wd, String rootPath, String oldName,
  32.                 String newName) {
  33.             print(“renamed “ + rootPath + ” : “ + oldName + ” -> “ + newName);
  34.         }
  35.         public void fileModified(int wd, String rootPath, String name) {
  36.             print(“modified “ + rootPath + ” : “ + name);
  37.         }
  38.         public void fileDeleted(int wd, String rootPath, String name) {
  39.             print(“deleted “ + rootPath + ” : “ + name);
  40.         }
  41.         public void fileCreated(int wd, String rootPath, String name) {
  42.             print(“created “ + rootPath + ” : “ + name);
  43.         }
  44.         void print(String msg) {
  45.             System.err.println(msg);
  46.         }
  47.     }
  48. }

三、FileAlterationMonitor

commons-io-2.2新出工具类,在monitor包下。功能类似Jnotify,不过是纯java实现,完美跨平台。
看代码,代码注释有详细的说明:

monitor工具类:

[java] view plain copy

  1. public class FileMonitorUtil {
  2.     public static FileAlterationMonitor addMonitor(String path){
  3.         FileAlterationMonitor monitor = new FileAlterationMonitor(100);//监控器
  4.         FileAlterationObserver observer = new FileAlterationObserver(path);//对某个路径的观察者
  5.         observer.addListener(new PushFileAlterationListener(path));//添加监听事件响应,与path无关,rsync同步需要
  6.         monitor.addObserver(observer);//将观察者添加到监控器
  7.         try {
  8.             monitor.start();//启动
  9.         } catch (Exception e) {
  10.             e.printStackTrace();
  11.         }
  12.         return monitor;//便于停止
  13.     }
  14.     public static void main(String[] args) {
  15.         String path = “E:\\test”;
  16.         FileAlterationMonitor monitor = FileMonitorUtil.addMonitor(path);
  17.         try {
  18.             Thread.sleep(10000);//如果不加休眠和停止操作,monitor将会一直监听
  19.             monitor.stop();//停止监控
  20.         } catch (Exception e) {
  21.             e.printStackTrace();
  22.         }
  23.     }
  24. }

监听响应类:实现FileAlterationListener接口,大家可以按需实现。

[java] view plain copy

  1. public class PushFileAlterationListener implements FileAlterationListener{
  2.     private String rootpath = “”;
  3.     public PushFileAlterationListener(String rootpath) {
  4.         this.rootpath = rootpath;
  5.     }
  6.     @Override
  7.     public void onDirectoryChange(File file) {
  8.     }
  9.     @Override
  10.     public void onDirectoryCreate(File file) {
  11.         RsyncQueue.addJob(new RsyncJob(rootpath, file.getParent(), “0”));//Rsync同步队列
  12.         System.out.println(“Directory create: “ + file.getAbsolutePath()+”  “+file.getParent());
  13.     }
  14.     @Override
  15.     public void onDirectoryDelete(File file) {
  16.         RsyncQueue.addJob(new RsyncJob(rootpath, file.getParent(), “0”));
  17.         System.out.println(“Directory delete: “ + file.getAbsolutePath()+”  “+file.getParent());
  18.     }
  19.     @Override
  20.     public void onFileChange(File file) {
  21.         RsyncQueue.addJob(new RsyncJob(rootpath, file.getParent(), “0”));
  22.         System.out.println(“File change: “ + file.getAbsolutePath()+”  “+file.getParent());
  23.     }
  24.     @Override
  25.     public void onFileCreate(File file) {
  26.         RsyncQueue.addJob(new RsyncJob(rootpath, file.getParent(), “0”));
  27.         System.out.println(“File created: “ + file.getAbsolutePath()+”  “+file.getParent());
  28.     }
  29.     @Override
  30.     public void onFileDelete(File file) {
  31.         RsyncQueue.addJob(new RsyncJob(rootpath, file.getParent(), “0”));
  32.         System.out.println(“File deleted: “ + file.getAbsolutePath()+”  “+file.getParent());
  33.     }
  34.     @Override
  35.     public void onStart(FileAlterationObserver filealterationobserver) {
  36.         System.out.println(“start”);
  37.     }
  38.     @Override
  39.     public void onStop(FileAlterationObserver filealterationobserver) {
  40.         System.out.println(“end”);
  41.     }
  42. }

注:

1、public FileAlterationMonitor():Construct a monitor with a default interval of 10 seconds。默认响应时间为10s,及你添加文件后可能要过10s你才接到通知。所以一般使用带时间参数的构造器(单位毫秒)。

2、也可以通过继承FileAlterationListenerAdaptor来实现监听,目前该类为空实现。两种方式各有优劣。

3、父目录的下的文件变动时,会触发2个事件:a,子文件FileChange;b,父目录的DirectoryChange事件;

4、重命名文件(夹),会同时触发:FileCreate和FileDelete
5、如果拷贝某个工程时,工程内的每个文件都会触发事件,所以队列添加事件的算法需要好好设计。

6、windows系统,文件拷贝过程不触发事件,拷完后触发FileChange,Linux,拷贝过程一直触发FileChange

总结:由于在window2003等系统,在拷贝文件结束后也不触发FileChange,所以要真正跨平台,还得结合Jnotify和FileAlteration

没有评论

发表评论

电子邮件地址不会被公开。