Java 文件监控,实时监控文件加载

本文转自:http://blog.csdn.net/chichengit/article/details/8259837

前段时间设计一个文件自动加载系统模块,功能就像是在Tomcat的webapps目录下发布war包那样,只要一有war包加载进来,tomcat立刻就会去解压这个war包,并把它挂载在tomcat上,供网络访问。

我这个程序的思路也正是这样,可以监控某一目录下的文件,包括文件的增加,删除,修改,正在加载,加载成功等事件,使用抽象类和接口方式来编写,要拓展此类,十分容易,当然这个也只是个人粗制滥造的一个小玩意,大有优化的空间。在JDK7.0中包含了文件监控的API,不过听说性能很不行,事件触发很不稳定,看来oracle收购了sun之后,Java前途一片渺茫啊....

先说说我设计的思路:启动一个不断循环的守护线程,不断检测某目录下的文件列表,并将这些文件名称和文件MD5校验码缓存起来,在下一个循环的时候直接从缓存中取出数据,进行对比,如果发现MD5校验不一样,说明文件被更新,还有文件增加,删除的事件,在代码中有相关的注释,下面开始贴代码

1,Monitor,这个是一个接口,开始时是设计用来做各种监控的,例如文件监控,内存监控,CPU监控,网络监控等,Monitor接口没有方法,只是一个接口标识

Java代码  复制代码  收藏代码
  1. package cn.std.run.monitor; 
  2.  
  3. public interface Monitor{ 
  4.  
[java]  view plain copy
  1. package cn.std.run.monitor;  
  2.   
  3. public interface Monitor{  
  4.   
  5. }  

2,FileMonitor,这是一个文件监控的接口,继承Monitor,定义了文件监控的几个方法,所有有关文件监控的实现类,都必须实现此接口

Java代码  复制代码  收藏代码
  1. package cn.std.run.monitor; 
  2.  
  3.  
  4. public interface FileMonitor extends Monitor ,Runnable{ 
  5.  
  6.     /** 文件删除 */ 
  7.     void deleteAction(Object fileName); 
  8.     /** 文件增加 */ 
  9.     void addAction(Object fileName); 
  10.     /** 文件更新 */ 
  11.     void updateAction(Object fileName); 
  12.     /** 正在加载 */ 
  13.     void isLoading(Object fileName); 
  14.     /** 加载成功 */ 
  15.     void loadSuccess(Object fileName); 
[java]  view plain copy
  1. package cn.std.run.monitor;  
  2.   
  3.   
  4. public interface FileMonitor extends Monitor ,Runnable{  
  5.   
  6.     /** 文件删除 */  
  7.     void deleteAction(Object fileName);  
  8.     /** 文件增加 */  
  9.     void addAction(Object fileName);  
  10.     /** 文件更新 */  
  11.     void updateAction(Object fileName);  
  12.     /** 正在加载 */  
  13.     void isLoading(Object fileName);  
  14.     /** 加载成功 */  
  15.     void loadSuccess(Object fileName);  
  16. }  

3,DiskFileMonitor,这是一个抽象类,实现FileMonitor接口,并对FileMonitor做了相关实现和拓展,提供给程序员后续开发的接口,程序员如果需要开发有关文件监控的相关功能,直接继承DiskFileMonitor类,就搞定

Java代码  复制代码  收藏代码
  1. package cn.std.run.monitor; 
  2.  
  3. import java.io.File; 
  4. import java.io.IOException; 
  5. import java.util.ArrayList; 
  6. import java.util.Enumeration; 
  7. import java.util.HashMap; 
  8. import java.util.List; 
  9. import java.util.Map; 
  10. import java.util.Vector; 
  11.  
  12. public abstract class DiskFileMonitor implements FileMonitor{ 
  13.  
  14.     private final String ServiceFilesKey = "ServiceFiles"
  15.     private final String ServiceFilesMapKey = "ServiceFilesMapKey"
  16.     private String filePath = "./src/cn/std/pool/cache"
  17.      
  18.     public DiskFileMonitor(String fpath) { 
  19.         try { 
  20.             filePath  = fpath; 
  21.             Vector<String> files = new Vector<String>(); 
  22.             getFiles(files, fpath); 
  23.             CacheMgr.putCache(ServiceFilesKey,files); 
  24.             Map<String,String> hm = new HashMap<String,String>(files.size()); 
  25.             for(String f:files){ 
  26.                 String fp = fpath+"/"+f; 
  27.                 fp = fp.replaceAll("//""/"); 
  28.                 try { 
  29.                     String hash = HashFile.getHash(fp, "MD5"); 
  30.                     hm.put(f, hash); 
  31.                 } catch (Exception e) { 
  32.                     e.printStackTrace(); 
  33.                 } 
  34.             } 
  35.             CacheMgr.putCache(ServiceFilesMapKey, hm); 
  36.             CacheMgr.lsCache(); 
  37.             //Vector ve = (Vector)CacheMgr.getCache(ServiceFilesKey); 
  38.         } catch (IOException e) { 
  39.             e.printStackTrace(); 
  40.         } 
  41.     } 
  42.      
  43.     /** 递归获取目录下的所有文件 */ 
  44.     private static void getFiles(Vector<String> ret,String fpath) throws IOException {  
  45.         File dir = new File(fpath);  
  46.         File[] files = dir.listFiles();  
  47.          
  48.         if (files == null)  
  49.             return;  
  50.         for (int i = 0; i < files.length; i++) {  
  51.             if (files[i].isDirectory()) {  
  52.                 getFiles(ret,files[i].getAbsolutePath());  
  53.             } else {  
  54.                 String fileName = files[i].getName(); 
  55.                 ret.addElement(fileName); 
  56.             }  
  57.         }  
  58.     } 
  59.      
  60.     @Override 
  61.     @SuppressWarnings("unchecked"
  62.     public void run() { 
  63.         try { 
  64.             Vector<String> notLoadFiles = new Vector<String>(); 
  65.             while(true){ 
  66.                 Vector<String> diskfiles = new Vector<String>(); 
  67.                 getFiles(diskfiles, filePath);//从磁盘中读出文件 
  68.                 //判断文件是否已经加载 
  69.                 Object obj = CacheMgr.getCache(ServiceFilesKey); 
  70.                 Vector<String> cachefiles = null
  71.                 if(obj instanceof Vector){ 
  72.                     cachefiles = (Vector<String>)obj; 
  73.                 } 
  74.                 if(null != cachefiles){ 
  75.                     int diskfilesSize = diskfiles.size(); 
  76.                     int cachefilesSize = cachefiles.size(); 
  77.                      
  78.                     //磁盘文件>缓存文件,说明磁盘中增加了文件 
  79.                     if(diskfilesSize > cachefilesSize){ 
  80.                         Enumeration<String> diskEn = diskfiles.elements(); 
  81.                         while(diskEn.hasMoreElements()){ 
  82.                             Object diskElement = diskEn.nextElement(); 
  83.                             if(cachefiles.contains(diskElement)){//如果缓存中已经包含了磁盘元素,进行下一个循环 
  84.                                 continue
  85.                             }else
  86.                                 notLoadFiles.addElement((String)diskElement); 
  87.                             } 
  88.                         }//end while  
  89.                     //磁盘中删除了文件 
  90.                     }else if(diskfilesSize < cachefilesSize){ 
  91.                         Enumeration<String> cacheEn = cachefiles.elements(); 
  92.                         while(cacheEn.hasMoreElements()){ 
  93.                             Object cacheElement = cacheEn.nextElement(); 
  94.                             if(diskfiles.contains(cacheElement)){//如果缓存中已经包含了磁盘元素,进行下一个循环 
  95.                                 continue
  96.                             }else
  97.                                 cachefiles.removeElement(cacheElement); 
  98.                             //  System.out.println(cacheElement+" 文件删除"); 
  99.                                 deleteAction(cacheElement); 
  100.                                 HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey); 
  101.                                 upmap.remove(cacheElement); 
  102.                             } 
  103.                         }//end while  
  104.                     //文件数量没有变化,分两种情况,1,删除N个文件同时又增加了N个文件。2,文件原封不动 
  105.                     }else { 
  106.                         Map<String,String> hm = (Map<String, String>) CacheMgr.getCache(ServiceFilesMapKey); 
  107.                         Enumeration<String> diskEn = diskfiles.elements(); 
  108.                         Vector<Object> isIn = new Vector<Object>(diskfilesSize); 
  109.                         while(diskEn.hasMoreElements()){ 
  110.                             Object diskElement = diskEn.nextElement(); 
  111.                             String diskfilepath = filePath+"/"+diskElement; 
  112.                             diskfilepath = diskfilepath.replace("//""/"); 
  113.                             String newhash = HashFile.getHash(diskfilepath, "MD5"); 
  114.                             String mapHash = hm.get(diskElement); 
  115.                             if(null != mapHash){//如果不为空,说明有这个文件 
  116.                                 isIn.addElement(diskElement); 
  117.                                 if(mapHash.equals(newhash)){ 
  118.                                     continue
  119.                                 }else
  120.                                     updateAction(diskElement); 
  121.                                     //更新文件hash 
  122.                                     HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey); 
  123.                                     upmap.put(diskElement.toString(),newhash); 
  124.                                 } 
  125.                             }else{//如果为空,说明重命名了一个文件 
  126.                             //  deleteAction(diskElement); 
  127.                                 addAction(diskElement); 
  128.                                 hm.put(diskElement.toString(), newhash); 
  129.                                 cachefiles.addElement(diskElement.toString()); 
  130.                                 isIn.addElement(diskElement); 
  131.                             }  
  132.                         }//end while 
  133.                          
  134.                         List<String> willRemove = new ArrayList<String>(hm.size()); 
  135.                         //遍历已经存在的元素,找出被重命名的元素 
  136.                         for(Map.Entry<String, String> m:hm.entrySet()){ 
  137.                             if(isIn.contains(m.getKey())){ 
  138.                                 continue
  139.                             }else
  140.                                 willRemove.add(m.getKey()); 
  141.                             } 
  142.                         } 
  143.                          
  144.                         for(String element:willRemove){ 
  145.                             hm.remove(element); 
  146.                             cachefiles.removeElement(element); 
  147.                             deleteAction(element); 
  148.                         } 
  149.                     } 
  150.                      
  151.                     if(notLoadFiles.size() == 0){ 
  152.                         //服务文件没有更新 
  153.                     }else
  154.                         //服务文件更新 
  155.                          
  156.                         Vector<String> loadedfiles = new Vector<String>(); 
  157.                         //此处加载服务文件 
  158.                         for(String name:notLoadFiles){ 
  159.                     //      System.out.println(name+" 未加载"); 
  160.                             addAction(name); 
  161.                     //      System.out.println(name+" 正在加载.."); 
  162.                             loadedfiles.addElement(name); 
  163.                             isLoading(name); 
  164.                     //      System.out.println(name+" 加载成功"); 
  165.                             cachefiles.addElement(name); 
  166.                             HashMap<String, String> hm = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey); 
  167.                             String path = filePath+"/"+name; 
  168.                             path = path.replace("//""/"); 
  169.                             hm.put(name,HashFile.getHash(path, "MD5")); 
  170.                             loadSuccess(name); 
  171.                             CacheMgr.lsCache(); 
  172.                         } 
  173.                         notLoadFiles.removeAll(loadedfiles); 
  174.                     } 
  175.                 } 
  176.                 Thread.sleep(500); 
  177.             }//end while(true) 
  178.         } catch (IOException e) { 
  179.             e.printStackTrace(); 
  180.         } catch (InterruptedException e) { 
  181.             e.printStackTrace(); 
  182.         } catch (Exception e) { 
  183.             e.printStackTrace(); 
  184.         } 
  185.     } 
  186.      
[java]  view plain copy
  1. package cn.std.run.monitor;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.Enumeration;  
  7. import java.util.HashMap;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10. import java.util.Vector;  
  11.   
  12. public abstract class DiskFileMonitor implements FileMonitor{  
  13.   
  14.     private final String ServiceFilesKey = "ServiceFiles";  
  15.     private final String ServiceFilesMapKey = "ServiceFilesMapKey";  
  16.     private String filePath = "./src/cn/std/pool/cache";  
  17.       
  18.     public DiskFileMonitor(String fpath) {  
  19.         try {  
  20.             filePath  = fpath;  
  21.             Vector<String> files = new Vector<String>();  
  22.             getFiles(files, fpath);  
  23.             CacheMgr.putCache(ServiceFilesKey,files);  
  24.             Map<String,String> hm = new HashMap<String,String>(files.size());  
  25.             for(String f:files){  
  26.                 String fp = fpath+"/"+f;  
  27.                 fp = fp.replaceAll("//""/");  
  28.                 try {  
  29.                     String hash = HashFile.getHash(fp, "MD5");  
  30.                     hm.put(f, hash);  
  31.                 } catch (Exception e) {  
  32.                     e.printStackTrace();  
  33.                 }  
  34.             }  
  35.             CacheMgr.putCache(ServiceFilesMapKey, hm);  
  36.             CacheMgr.lsCache();  
  37.             //Vector ve = (Vector)CacheMgr.getCache(ServiceFilesKey);  
  38.         } catch (IOException e) {  
  39.             e.printStackTrace();  
  40.         }  
  41.     }  
  42.       
  43.     /** 递归获取目录下的所有文件 */  
  44.     private static void getFiles(Vector<String> ret,String fpath) throws IOException {   
  45.         File dir = new File(fpath);   
  46.         File[] files = dir.listFiles();   
  47.           
  48.         if (files == null)   
  49.             return;   
  50.         for (int i = 0; i < files.length; i++) {   
  51.             if (files[i].isDirectory()) {   
  52.                 getFiles(ret,files[i].getAbsolutePath());   
  53.             } else {   
  54.                 String fileName = files[i].getName();  
  55.                 ret.addElement(fileName);  
  56.             }   
  57.         }   
  58.     }  
  59.       
  60.     @Override  
  61.     @SuppressWarnings("unchecked")  
  62.     public void run() {  
  63.         try {  
  64.             Vector<String> notLoadFiles = new Vector<String>();  
  65.             while(true){  
  66.                 Vector<String> diskfiles = new Vector<String>();  
  67.                 getFiles(diskfiles, filePath);//从磁盘中读出文件  
  68.                 //判断文件是否已经加载  
  69.                 Object obj = CacheMgr.getCache(ServiceFilesKey);  
  70.                 Vector<String> cachefiles = null;  
  71.                 if(obj instanceof Vector){  
  72.                     cachefiles = (Vector<String>)obj;  
  73.                 }  
  74.                 if(null != cachefiles){  
  75.                     int diskfilesSize = diskfiles.size();  
  76.                     int cachefilesSize = cachefiles.size();  
  77.                       
  78.                     //磁盘文件>缓存文件,说明磁盘中增加了文件  
  79.                     if(diskfilesSize > cachefilesSize){  
  80.                         Enumeration<String> diskEn = diskfiles.elements();  
  81.                         while(diskEn.hasMoreElements()){  
  82.                             Object diskElement = diskEn.nextElement();  
  83.                             if(cachefiles.contains(diskElement)){//如果缓存中已经包含了磁盘元素,进行下一个循环  
  84.                                 continue;  
  85.                             }else{  
  86.                                 notLoadFiles.addElement((String)diskElement);  
  87.                             }  
  88.                         }//end while   
  89.                     //磁盘中删除了文件  
  90.                     }else if(diskfilesSize < cachefilesSize){  
  91.                         Enumeration<String> cacheEn = cachefiles.elements();  
  92.                         while(cacheEn.hasMoreElements()){  
  93.                             Object cacheElement = cacheEn.nextElement();  
  94.                             if(diskfiles.contains(cacheElement)){//如果缓存中已经包含了磁盘元素,进行下一个循环  
  95.                                 continue;  
  96.                             }else{  
  97.                                 cachefiles.removeElement(cacheElement);  
  98.                             //  System.out.println(cacheElement+" 文件删除");  
  99.                                 deleteAction(cacheElement);  
  100.                                 HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);  
  101.                                 upmap.remove(cacheElement);  
  102.                             }  
  103.                         }//end while   
  104.                     //文件数量没有变化,分两种情况,1,删除N个文件同时又增加了N个文件。2,文件原封不动  
  105.                     }else {  
  106.                         Map<String,String> hm = (Map<String, String>) CacheMgr.getCache(ServiceFilesMapKey);  
  107.                         Enumeration<String> diskEn = diskfiles.elements();  
  108.                         Vector<Object> isIn = new Vector<Object>(diskfilesSize);  
  109.                         while(diskEn.hasMoreElements()){  
  110.                             Object diskElement = diskEn.nextElement();  
  111.                             String diskfilepath = filePath+"/"+diskElement;  
  112.                             diskfilepath = diskfilepath.replace("//""/");  
  113.                             String newhash = HashFile.getHash(diskfilepath, "MD5");  
  114.                             String mapHash = hm.get(diskElement);  
  115.                             if(null != mapHash){//如果不为空,说明有这个文件  
  116.                                 isIn.addElement(diskElement);  
  117.                                 if(mapHash.equals(newhash)){  
  118.                                     continue;  
  119.                                 }else{  
  120.                                     updateAction(diskElement);  
  121.                                     //更新文件hash  
  122.                                     HashMap<String,String> upmap = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);  
  123.                                     upmap.put(diskElement.toString(),newhash);  
  124.                                 }  
  125.                             }else{//如果为空,说明重命名了一个文件  
  126.                             //  deleteAction(diskElement);  
  127.                                 addAction(diskElement);  
  128.                                 hm.put(diskElement.toString(), newhash);  
  129.                                 cachefiles.addElement(diskElement.toString());  
  130.                                 isIn.addElement(diskElement);  
  131.                             }   
  132.                         }//end while  
  133.                           
  134.                         List<String> willRemove = new ArrayList<String>(hm.size());  
  135.                         //遍历已经存在的元素,找出被重命名的元素  
  136.                         for(Map.Entry<String, String> m:hm.entrySet()){  
  137.                             if(isIn.contains(m.getKey())){  
  138.                                 continue;  
  139.                             }else{  
  140.                                 willRemove.add(m.getKey());  
  141.                             }  
  142.                         }  
  143.                           
  144.                         for(String element:willRemove){  
  145.                             hm.remove(element);  
  146.                             cachefiles.removeElement(element);  
  147.                             deleteAction(element);  
  148.                         }  
  149.                     }  
  150.                       
  151.                     if(notLoadFiles.size() == 0){  
  152.                         //服务文件没有更新  
  153.                     }else{  
  154.                         //服务文件更新  
  155.                           
  156.                         Vector<String> loadedfiles = new Vector<String>();  
  157.                         //此处加载服务文件  
  158.                         for(String name:notLoadFiles){  
  159.                     //      System.out.println(name+" 未加载");  
  160.                             addAction(name);  
  161.                     //      System.out.println(name+" 正在加载..");  
  162.                             loadedfiles.addElement(name);  
  163.                             isLoading(name);  
  164.                     //      System.out.println(name+" 加载成功");  
  165.                             cachefiles.addElement(name);  
  166.                             HashMap<String, String> hm = (HashMap<String,String>)CacheMgr.getCache(ServiceFilesMapKey);  
  167.                             String path = filePath+"/"+name;  
  168.                             path = path.replace("//""/");  
  169.                             hm.put(name,HashFile.getHash(path, "MD5"));  
  170.                             loadSuccess(name);  
  171.                             CacheMgr.lsCache();  
  172.                         }  
  173.                         notLoadFiles.removeAll(loadedfiles);  
  174.                     }  
  175.                 }  
  176.                 Thread.sleep(500);  
  177.             }//end while(true)  
  178.         } catch (IOException e) {  
  179.             e.printStackTrace();  
  180.         } catch (InterruptedException e) {  
  181.             e.printStackTrace();  
  182.         } catch (Exception e) {  
  183.             e.printStackTrace();  
  184.         }  
  185.     }  
  186.       
  187. }  

4,MyDiskFileMonitor,这是一个测试类,程序启动之后直接监控指定目录,指定目录下如果有文件变化,MyDiskFileMonitor会马上得到调用,例如,如果增加文件,AddAction方法会被调用,参数是新增加的文件名

Java代码  复制代码  收藏代码
  1. package cn.std.run.monitor; 
  2.  
  3. public class MyDiskFileMonitor extends DiskFileMonitor{ 
  4.  
  5.     public MyDiskFileMonitor(String fpath) { 
  6.         super(fpath); 
  7.     } 
  8.  
  9.     @Override 
  10.     public void deleteAction(Object fileName) { 
  11.         System.out.println(fileName +" 元素删除"); 
  12.     } 
  13.  
  14.     @Override 
  15.     public void addAction(Object fileName) { 
  16.         System.out.println(fileName +" 新增元素"); 
  17.          
  18.     } 
  19.  
  20.     @Override 
  21.     public void updateAction(Object fileName) { 
  22.         System.out.println(fileName +" 元素更新"); 
  23.          
  24.     } 
  25.  
  26.  
  27.     @Override 
  28.     public void isLoading(Object fileName) { 
  29.         System.out.println(fileName +" 正在加载"); 
  30.     } 
  31.  
  32.     @Override 
  33.     public void loadSuccess(Object fileName) { 
  34.         System.out.println(fileName +" 加载成功"); 
  35.     } 
  36.      
  37.     public static void main(String[] args) { 
  38.         String filePath = "F:/monitor"
  39.         MyDiskFileMonitor mo = new MyDiskFileMonitor(filePath); 
  40.         new Thread(mo).start(); 
  41.     } 
[java]  view plain copy
  1. package cn.std.run.monitor;  
  2.   
  3. public class MyDiskFileMonitor extends DiskFileMonitor{  
  4.   
  5.     public MyDiskFileMonitor(String fpath) {  
  6.         super(fpath);  
  7.     }  
  8.   
  9.     @Override  
  10.     public void deleteAction(Object fileName) {  
  11.         System.out.println(fileName +" 元素删除");  
  12.     }  
  13.   
  14.     @Override  
  15.     public void addAction(Object fileName) {  
  16.         System.out.println(fileName +" 新增元素");  
  17.           
  18.     }  
  19.   
  20.     @Override  
  21.     public void updateAction(Object fileName) {  
  22.         System.out.println(fileName +" 元素更新");  
  23.           
  24.     }  
  25.   
  26.   
  27.     @Override  
  28.     public void isLoading(Object fileName) {  
  29.         System.out.println(fileName +" 正在加载");  
  30.     }  
  31.   
  32.     @Override  
  33.     public void loadSuccess(Object fileName) {  
  34.         System.out.println(fileName +" 加载成功");  
  35.     }  
  36.       
  37.     public static void main(String[] args) {  
  38.         String filePath = "F:/monitor";  
  39.         MyDiskFileMonitor mo = new MyDiskFileMonitor(filePath);  
  40.         new Thread(mo).start();  
  41.     }  
  42. }  

好了,运行起来看看结果:


另外,附上我自己封装的一个用来保存数据的类,暂定义是Cache,因为我开发这个实际上是准备用来做一个自己的缓存的功能的,完毕。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值