利用WatchService實現文件監視


Java.nio.file WatchService類圖

  • FileSystem:當前系統默認的文件系統。
  • WatchService:文件系統監視服務的接口類,它的具體實現由監視服務提供者負責加載(不同的操作系統實現不同的加載類,如windows的WindowsWatchService類)。
  • Watchable:實現了Watchable接口的對象才能注冊監視服務WatchService,由於Path類實現了Watchable接口,固可以通過Path類對文件目錄進行監聽。
  • WatchKey:該類代表着WatchService類和Watchable類的注冊關系,WatchKey在Watchable對象(Path對象)向WatchService注冊的時候被創建。

 

實現代碼與解析

/*
* 創建所需要監控目錄樹的根目錄File對象。
* */
File file = new File("/delete");
        
/*
* 轉換成Path對象。
* */
Path parentPath = file.toPath();
/*
*創建監視服務類WatchService對象。
* */
WatchService watchService = FileSystems.getDefault().newWatchService();
        
/*
* 對根目錄注冊監聽服務。
* 1.ENTRY_CREATE:創建條目時返回的事件類型
* 2.ENTRY_DELETE:刪除條目時返回的事件類型
* 3.ENTRY_MODIFY:修改條目時返回的事件類型
* 4.OVERFLOW:表示事件丟失或被丟棄,不必要注冊該事件類型
* */
parentPath.register(watchService
        , StandardWatchEventKinds.ENTRY_CREATE
        ,StandardWatchEventKinds.ENTRY_DELETE
        ,StandardWatchEventKinds.ENTRY_MODIFY);
/*
* -------遍歷根目錄及子目錄,將其全都注冊監聽服務-------
* 創建鏈表結構存儲File對象。
* 添加根目錄的對象到鏈表尾。
* */
LinkedList<File> linkfile = new LinkedList<>();
linkfile.addLast(file);

/*
* 當鏈表還有File對象時進入循環。
* */
while(linkfile.size()>0){
/*
* 移除鏈表表頭的File對象並返回給f
* 使用listFiles()方法生成File數組,
* 數組儲存f代表目錄中的File對象。
* */
   File f = linkfile.removeFirst();
   File[] files = f.listFiles();
   for (File f1:files
    ) {
/*
* 遍歷數組中的每一個File對象。
* 判斷其是不是目錄,
* 如果是目錄則將其添加到鏈表尾,
* 只有目錄可以注冊監聽服務。
* */
   if(f1.isDirectory()){
      linkfile.addLast(f1);
                    
/*
* 給當前目錄注冊監聽服務。
* */
f1.toPath().register(watchService
       , StandardWatchEventKinds.ENTRY_CREATE
       ,StandardWatchEventKinds.ENTRY_DELETE
       ,StandardWatchEventKinds.ENTRY_MODIFY);
         }
    }
}
/*
* 創建一個線程用來獲取監聽事件WatchEvent對象
* */
new Thread(()->{
    /*
    * 構建無限循環等待事件發生
    * */
    while(true){
        
        /*
        * 通過WatchService對象tack()方法產生WatchKey實例key
        * */
        WatchKey key = null;
        try {
            key = watchService.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        /*
        * WatchKey對象key輪詢事件(pollEvents())獲得事件隊列
        * 遍歷事件(WatchEvent)獲得變化文件的信息
        * */
        for (WatchEvent event: key.pollEvents()
        ) {
            /*
            * event.context()返回Object類型,可轉化為String和Path類型。
            * event.kind()返回事件種類。
            * */
            Path file2 = (Path)event.context();
            String str = file2.toFile().getAbsolutePath();
            System.out.println(str+" "+event.kind().toString());
        }
        /*
        * 重置WatchKey對象,使事件對象回到隊列。
        * */
        key.reset();
    }
}).start();
/*
 * 測試代碼,改變文件
 * */
new File("/delete/123.txt").createNewFile();
new File("/delete/create").mkdir();
new File("/delete/234.txt").delete();
new File("/delete/create/456.txt").createNewFile();
/*
* Output:
D:\專業\ideajava\CSDN\123.txt ENTRY_CREATE
D:\專業\ideajava\CSDN\create ENTRY_CREATE
D:\專業\ideajava\CSDN\234.txt ENTRY_MODIFY
D:\專業\ideajava\CSDN\234.txt ENTRY_DELETE
D:\專業\ideajava\CSDN\create ENTRY_MODIFY
* */

注意:

  • WatchService監聽在系統支持的情況下采用事件驅動機制,可降檔為掃描式機制。
  • 事件發生后需使用reset()方法重置WatchKey對象,否則事件所屬的目錄的改動通知只會發生一次。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM