たとえばdir\file.txt
が変更されたことをWatchService
で検出したい場合、次のようなコードを書きたくなりますが、これは実行時例外(NotDirectoryException
)が発生します。
var file = Paths.get("dir", "file.txt");
var watcher = FileSystems.getDefault().newWatchService();
file.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
Path::register
のJavaDocにもある通り、WatchService
の登録対象はディレクトリです。あるいはWatchService
は登録したディレクトリの配下にあるファイルやディレクトリに発生したイベントを監視している、と言い換えてもいいでしょう。よって特定のファイルのイベントだけを検出したい場合は、たとえば次のような工夫が必要になります。
var file = Paths.get("dir", "file.txt");
var directory = file.getParent();
var watcher = FileSystems.getDefault().newWatchService();
directory.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
// 割り込みなどで中断するまで、file.txtを監視し続ける。
while (true) {
var watchKey = watcher.take();
for (var event : watchKey.pollEvents()) {
var modified = (Path) event.context();
if (modified.equals(file.getFileName())) {
// Do Something
}
}
}
WatchEvent::context
でイベントが発生したエントリの情報を取得できます。WatchEvent::context
の戻り値はObject
ですが、実態としてはPath
オブジェクトが返ってくるので、上記の例ではキャストして、変数modified
としています。
またmodified
に格納されたPath
オブジェクトは、WatchService
に登録されたディレクトリからの相対パスになっています。要するにvar modified = Paths.get("file.txt");
となっているため、equals
などで比較する場合は注意する必要があります。