首页 > 代码库 > 使用 Watch Service API 觀察檔案系統

使用 Watch Service API 觀察檔案系統

在 Java 7 以前,如果要觀察一個目錄下的檔案是否有異動 (新增、修改、刪除),唯一的辦法就是開啟一個 thread,每隔一段時間去檢查一下,當發現有異動,發出異動的訊息。Java 7 提供了 Watch Service API 解決了這個問題,現在不需要再這麼麻煩且浪費系統資源了,透過這組 API 程式可以很優雅、簡單的監控檔案系統的異動狀況。 如下的程式,會監控 D:\temp 這個目錄,如果這個目錄有任何檔案新增、修改、刪除,就會產生 event。

 1 package idv.steven.nio2;
 2 
 3 import java.io.IOException;
 4 import java.nio.file.FileSystems;
 5 import java.nio.file.Path;
 6 import java.nio.file.Paths;
 7 import java.nio.file.StandardWatchEventKinds;
 8 import java.nio.file.WatchEvent;
 9 import java.nio.file.WatchKey;
10 import java.nio.file.WatchService;
11 
12 public class WatchFile {
13     
14     public void run() {
15         final Path path = Paths.get("D:/temp");
16         WatchService watchService;
17         try {
18             watchService = FileSystems.getDefault().newWatchService();
19             
20             path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE,
21                     StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
22 
23             while (true) {
24                 final WatchKey key = watchService.take();
25                 
26                 for (WatchEvent<?> watchEvent : key.pollEvents()) {
27                     final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent;
28                     final Path filename = watchEventPath.context();
29                     
30                     System.out.println("kind: " + watchEvent.kind().toString());
31                     System.out.println("filename: " + filename.toString());
32                 }
33                 
34                 break;
35             }
36 
37             watchService.close();
38             System.out.println("exit");
39         } catch (IOException | InterruptedException e) {
40             e.printStackTrace();
41         }
42     }
43 
44     public static void main(String[] args) {
45         new WatchFile().run();
46     }
47 }

 現在解釋一下程式:

  • Line 18: 建立一個檔案系統的監視服務。
  • Line 19: 把監視服務註冊到我們要監視的路徑 (D:\temp),並指定要監視的事件類別,這裡指定「新增」、「修改」、「刪除」都要監視。
  • Line 24: 程式會停在這一行,開始監視。
  • Line 26~34: 監視的目錄有異動,產生的事件在這裡處理,我們很簡單的將事件類別和檔案名稱印出來。
  • Line 37: 關閉監視服務。

Line 24 行要特別說明,上述程式呼叫 take() 是方法之一,完整的說明如下:

  • poll(): If no key is available, it returns immediately a null value.
  • poll(long, TimeUnit): If no key is available, it waits the specified time and tries again. If still no key is available, then it returns null. The time period is indicated as a long number, while the TimeUnit argument determines whether the specified time is minutes, seconds, milliseconds, or some other unit of time.
  • take(): If no key is available, it waits until a key is queued or the infinite loop is stopped for any of several different reasons.