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對象,否則事件所屬的目錄的改動通知只會發生一次。