當(dāng)文件系統(tǒng)中的對象被修改時,我們可以監(jiān)聽watch
服務(wù)以獲取警報。java.nio.file
包中的以下類和接口提供watch
服務(wù)。
Watchable
對象表示可以被監(jiān)視的文件系統(tǒng)對象。Watchable
對象可以向watch
服務(wù)注冊。Path
對象是一個Watchable
對象。
WatchService
表示觀察服務(wù)。當(dāng)一個對象使用WatchService
注冊時,WatchService
返回一個WatchKey
作為注冊的令牌。WatchEvent
表示注冊到監(jiān)視服務(wù)的對象上的事件。 它的kind()
方法返回發(fā)生的事件的類型。
它的context()
方法返回一個Path
對象,它表示事件發(fā)生的條目。count()
方法返回特定通知的事件發(fā)生次數(shù)。 如果它返回的值大于1
,那么它是一個重復(fù)的事件。
WatchEvent.Kind <T>
表示發(fā)生的事件的類型。StandardWatchEventKinds
類定義了用于表示事件種類的常量,如下所示。
OVERFLOW
表示丟失或丟棄的事件。創(chuàng)建觀察服務(wù)用來觀察目錄,以進(jìn)行進(jìn)一步更改。
WatchService ws = FileSystems.getDefault().newWatchService();
要使用Watch
服務(wù)注冊目錄,請使用register()
方法,該方法將返回一個WatchKey
對象作為注冊令牌。
// 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);
要取消注冊,請使用WatchKey
的cancel()
方法。當(dāng)注冊目錄時,其WatchKey
處于就緒狀態(tài)??梢酝ㄟ^手表服務(wù)注冊多個目錄。
要從監(jiān)視服務(wù)隊列中檢索WatchKey
,請使用WatchService
對象的take()
或poll()
方法檢索并刪除發(fā)出信號并排隊的WatchKey
。take()
方法等待,直到WatchKey
可用。poll()
方法可用于為等待指定超時時間值。
以下代碼使用無限循環(huán)來檢索發(fā)出信號的WatchKey
。
while(true) {
WatchKey key = ws.take();
}
WatchKey
的pollEvents()
方法檢索并刪除其所有掛起的事件。它返回一個WatchEvent
的列表-List
。List
的每個元素代表WatchKey
上的一個事件。
以下代碼顯示了處理事件的典型邏輯:
while(true) {
WatchKey key = ws.take();
// Process all events of the WatchKey
for(WatchEvent<?> event : key.pollEvents()) {
// Process each event here
}
}
如果要重置WatchKey
對象,通過調(diào)用它的reset()
方法來再次接收事件通知。
reset()
方法將WatchKey
置于就緒狀態(tài)。如果WatchKey
仍然有效,reset()
方法返回true
,否則它返回false
。
如果WatchKey
被取消或其監(jiān)視服務(wù)關(guān)閉,它可能會失效。
// Reset the WatchKey
boolean isKeyValid = key.reset();
if (!isKeyValid) {
System.out.println("No longer watching " + dirToWatch);
}
WatchService
是可自動關(guān)閉的??梢栽?code>try-with-resources塊中創(chuàng)建一個WatchService
對象,當(dāng)程序退出塊時,它會自動關(guān)閉。
以下代碼顯示了如何實現(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();
}
}
}