Java 目錄事件

2018-02-05 11:45 更新

Java IO教程 - Java目錄事件


當(dāng)文件系統(tǒng)中的對(duì)象被修改時(shí),我們可以監(jiān)聽watch服務(wù)以獲取警報(bào)。

java.nio.file包中的以下類和接口提供watch服務(wù)。

  • Watchable接口
  • WatchService接口
  • WatchKey接口
  • WatchEvent接口
  • WatchEvent.Kind接口
  • StandardWatchEventKinds類

可監(jiān)視對(duì)象表示可以被監(jiān)視的文件系統(tǒng)對(duì)象??捎^看對(duì)象可以向手表服務(wù)注冊(cè)。

Path對(duì)象是一個(gè)Watchable對(duì)象。

WatchService表示觀察服務(wù)。當(dāng)一個(gè)對(duì)象使用WatchService注冊(cè)時(shí),WatchService返回一個(gè)WatchKey作為注冊(cè)的令牌。

WatchEvent表示注冊(cè)到監(jiān)視服務(wù)的對(duì)象上的事件。它的kind()方法返回發(fā)生的事件的類型。

它的context()方法返回一個(gè)Path對(duì)象,它表示事件發(fā)生的條目。

count()方法返回特定通知的事件發(fā)生次數(shù)。 如果它返回大于1的值,那么它是一個(gè)重復(fù)的事件。

WatchEvent.Kind <T>表示發(fā)生的事件的類型。

StandardWatchEventKinds類定義了用于表示事件種類的常量,如下所示。

  • ENTRY_CREATE
  • ENTRY_DELETE
  • ENTRY_MODIFY
  • OVERFLOW

OVERFLOW表示丟失或丟棄的事件。

創(chuàng)建觀察服務(wù)以觀察目錄以進(jìn)行更改。

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

要使用Watch服務(wù)注冊(cè)目錄,使用register()方法,該方法將返回一個(gè)WatchKey對(duì)象作為注冊(cè)令牌。

// Get  a  Path  object for C:\myName  directory  to watch
Path  dirToWatch  = Paths.get("C:\\myName");
WatchKey token   = dirToWatch.register(ws, ENTRY_CREATE,  ENTRY_MODIFY,  ENTRY_DELETE);

要取消注冊(cè),請(qǐng)使用WatchKey的cancel()方法。

當(dāng)注冊(cè)目錄時(shí),其WatchKey處于就緒狀態(tài)。

我們可以通過手表服務(wù)注冊(cè)多個(gè)目錄。

要從監(jiān)視服務(wù)隊(duì)列中檢索WatchKey,使用WatchService對(duì)象的take()或poll()方法來檢索和刪除發(fā)出信號(hào)并排隊(duì)的WatchKey。

take()方法等待,直到WatchKey可用。poll()方法允許我們?yōu)榈却付ǔ瑫r(shí)。

以下代碼使用無限循環(huán)來檢索發(fā)出信號(hào)的WatchKey。

while(true)  {
    WatchKey key  = ws.take();
}

處理事件

WatchKey的pollEvents()方法檢索并刪除所有掛起的事件。它返回一個(gè)WatchEvent的列表。 List的每個(gè)元素代表WatchKey上的一個(gè)事件。

以下代碼顯示了處理事件的典型邏輯:

while(true)  {
    WatchKey key  = ws.take();
    // Process all  events of  the   WatchKey 
    for(WatchEvent<?> event  : key.pollEvents())  {
       // Process each  event here
    }
}

處理事件后重置WatchKey

我們需要重置WatchKey對(duì)象,通過調(diào)用其reset()方法來再次接收事件通知。

reset()方法將WatchKey置于就緒狀態(tài)。如果WatchKey仍然有效,reset()方法返回true。 否則,它返回false。

如果WatchKey被取消或其監(jiān)視服務(wù)關(guān)閉,它可能會(huì)失效。

// Reset   the   WatchKey
boolean isKeyValid = key.reset();
if (!isKeyValid)  {
    System.out.println("No  longer  watching "  + dirToWatch);
}

WatchService是可自動(dòng)關(guān)閉的。我們可以在try-with-resources中創(chuàng)建一個(gè)WatchService的對(duì)象塊,當(dāng)程序退出塊時(shí)它將自動(dòng)關(guān)閉。

例子

以下代碼顯示了如何實(shí)現(xiàn)監(jiān)視服務(wù)以監(jiān)視目錄中的更改。

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
import static java.nio.file.StandardWatchEventKinds.OVERFLOW;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

public class Main {
  public static void main(String[] args) {
    try (WatchService ws = FileSystems.getDefault().newWatchService()) {
      Path dirToWatch = Paths.get("C:\\myName");
      dirToWatch.register(ws, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
      while (true) {
        WatchKey key = ws.take();
        for (WatchEvent<?> event : key.pollEvents()) {
          Kind<?> eventKind = event.kind();
          if (eventKind == OVERFLOW) {
            System.out.println("Event  overflow occurred");
            continue;
          }
          WatchEvent<Path> currEvent = (WatchEvent<Path>) event;
          Path dirEntry = currEvent.context();
          System.out.println(eventKind + "  occurred on  " + dirEntry);
        }
        boolean isKeyValid = key.reset();
        if (!isKeyValid) {
          System.out.println("No  longer  watching " + dirToWatch);
          break;
        }
      }
    } catch (IOException | InterruptedException e) {
      e.printStackTrace();
    }
  }
}
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)