Java目錄事件
當文件系統中的對象被修改時,我們可以監聽watch
服務以獲取警報。java.nio.file
包中的以下類和接口提供watch
服務。
- Watchable接口
- WatchService接口
- WatchKey接口
- WatchEvent接口
- WatchEvent.Kind接口
- StandardWatchEventKinds類
Watchable
對象表示可以被監視的文件系統對象。Watchable
對象可以向watch
服務註冊。Path
對象是一個Watchable
對象。
WatchService
表示觀察服務。當一個對象使用WatchService
註冊時,WatchService
返回一個WatchKey
作爲註冊的令牌。WatchEvent
表示註冊到監視服務的對象上的事件。 它的kind()
方法返回發生的事件的類型。
它的context()
方法返回一個Path
對象,它表示事件發生的條目。count()
方法返回特定通知的事件發生次數。 如果它返回的值大於1
,那麼它是一個重複的事件。
WatchEvent.Kind <T>
表示發生的事件的類型。StandardWatchEventKinds
類定義了用於表示事件種類的常量,如下所示。
- ENTRY_CREATE
- ENTRY_DELETE
- ENTRY_MODIFY
- OVERFLOW
OVERFLOW
表示丟失或丟棄的事件。創建觀察服務用來觀察目錄,以進行進一步更改。
WatchService ws = FileSystems.getDefault().newWatchService();
要使用Watch
服務註冊目錄,請使用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()
方法。當註冊目錄時,其WatchKey
處於就緒狀態。可以通過手錶服務註冊多個目錄。
要從監視服務隊列中檢索WatchKey
,請使用WatchService
對象的take()
或poll()
方法檢索並刪除發出信號並排隊的WatchKey
。take()
方法等待,直到WatchKey
可用。poll()
方法可用於爲等待指定超時時間值。
以下代碼使用無限循環來檢索發出信號的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
如果要重置WatchKey
對象,通過調用它的reset()
方法來再次接收事件通知。
reset()
方法將WatchKey
置於就緒狀態。如果WatchKey
仍然有效,reset()
方法返回true
,否則它返回false
。
如果WatchKey
被取消或其監視服務關閉,它可能會失效。
// Reset the WatchKey
boolean isKeyValid = key.reset();
if (!isKeyValid) {
System.out.println("No longer watching " + dirToWatch);
}
WatchService
是可自動關閉的。可以在try-with-resources
塊中創建一個WatchService
對象,當程序退出塊時,它會自動關閉。
示例
以下代碼顯示瞭如何實現監視服務以監視目錄中的更改。
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();
}
}
}