NIO 之 WatchService

NIO 之 WatchService

Java 1.6版本之前是不存在目錄監控的API的。若是要實現這種功能必需要本身遍歷目錄,記錄各個文件的狀況,而後定時所有遍歷一次,從 JDK7 以後出現了 WatchService 類,實現了對目錄下文件的監控。java

總體流程

整個監控目錄文件操做的流程大體以下:操作系統

  1. 獲取 WatchService
  2. 註冊指定目錄的監視器 WatchService
  3. 等待目錄下的文件發生變化
  4. 對發生變化的文件進行操做

獲取 WatchService 實例

WatchService 類的實現其實是對操做系統的文件監視器的封裝,相比以前的手動實現,優雅了很多。由於不須要遍歷文件總體而言效率也高不少。如下爲獲取 WatchService 實例的代碼,經過 FileSystem.getDefault() 可看出並不是是本身實現的。從 newWatchService() 方法名看, WatchService 能夠獲取多個。.net

WatchService watchService = FileSystems.getDefault().newWatchService();

實際上調用此方法後,程序會新開一個線程,監視文件變化發出的信號,此時線程還沒有就緒。線程

爲目錄註冊監視器

有了監視器,接下來咱們須要註冊監視器了。code

Path path = Paths.get("src");
WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

註冊監視器須要用到 Path 實例,該實例對應的必須是一個目錄,不容許是一個文件。
方法比較簡單,就是說爲目錄註冊一個監視器,監視目錄下文件的變化。
關於 StandardWatchEventKinds.ENTRY_MODIFY ,表示監視文件的修改事件,它是 WatchEvent.Kind<?> 的實現類。
看起來它像是枚舉,實際上它並非。JDK 中幫咱們定義了三種事件,新增、修改和刪除。orm

獲取目錄下的變化

獲取目錄的變化須要使用 WatchServicetake() 方法或 poll() 方法。對象

WatchKey key = watchService.take();
WatchKey pollKey = watchService.poll();

take() 是一個阻塞方法,會等待監視器發出的信號才返回。
poll() 是一個非阻塞方法,會當即返回當時監視器中是否有信號。
返回的 WatchKey 對象,其實是一個單例,和以前 path.register() 方法返回的實例是同一個。它只能保存某一時間點的文件變化信息。blog

處理文件變化事件

List<WatchEvent<?>> events = key.pollEvents();
for (WatchEvent<?> pollEvent : events) {
    Object o = pollEvent.context();
    WatchEvent.Kind kind = pollEvent.kind();
}

key.reset();

pollEvents() 用於獲取文件變化事件,只能獲取一次,不能重複獲取,相似隊列的形式。
context() 返回觸發該事件的那個文件或目錄的路徑(相對路徑)
kind() 返回事件類型(ENTRY_CREATE、ENTRY_DELETE、ENTRY_MODIFY之一)
reset() 每次調用 WatchService 的 take() 或 poll() 方法時須要經過本方法重置。隊列

一個簡單的例子

public void watchServiceExample() throws IOException, InterruptedException {
    WatchService watchService = FileSystems.getDefault().newWatchService();

    Path path = Paths.get("D:/code");

    WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

    while (true) {
        // 嘗試獲取下一個變化信息的監控池,若是沒有變化則一直等待
        WatchKey key = watchService.take();

        for (WatchEvent<?> pollEvent : key.pollEvents()) {
            System.out.println(String.format("%s is %s.", pollEvent.context().toString(), pollEvent.kind().name().substring(6)));
        }

        if (!key.reset()) {
            break;
        }
    }
}

總結

WatchService 的優勢就不用多說了,這裏就說一個缺點: 只能監視當前目錄下的文件和目錄,不能監視子目錄事件


參考

[瘋狂Java]NIO.2:WatchService、WatchKey(監控文件變化)

本文若有問題,歡迎在評論區中指正。

相關文章
相關標籤/搜索