當檔案系統中的物件被修改時,我們可以監聽watch
服務以獲取警報。java.nio.file
包中的以下類和介面提供watch
服務。
Watchable
物件表示可以被監視的檔案系統物件。Watchable
物件可以向watch
服務註冊。Path
物件是一個Watchable
物件。
WatchService
表示觀察服務。當一個物件使用WatchService
註冊時,WatchService
返回一個WatchKey
作為註冊的令牌。WatchEvent
表示註冊到監視服務的物件上的事件。 它的kind()
方法返回發生的事件的型別。
它的context()
方法返回一個Path
物件,它表示事件發生的條目。count()
方法返回特定通知的事件發生次數。 如果它返回的值大於1
,那麼它是一個重複的事件。
WatchEvent.Kind <T>
表示發生的事件的型別。StandardWatchEventKinds
類定義了用於表示事件種類的常數,如下所示。
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
物件,通過呼叫它的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();
}
}
}