當(dāng)文件系統(tǒng)中的對(duì)象被修改時(shí),我們可以監(jiān)聽watch服務(wù)以獲取警報(bào)。
java.nio.file包中的以下類和接口提供watch服務(wù)。
可監(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類定義了用于表示事件種類的常量,如下所示。
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對(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(); } } }
更多建議: