I have a WatchService
that watches a directory tree for ENTRY_CREATE
, ENTRY_DELETE
AND ENTRY-MODIFY
events. The problem is that the context of a WatchEvent<?>
gives only a Path object. On delete events, I'm unsure of if the path referred to a directory of a regular file.
WatchKey key = null;
try {
key = watcher.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (WatchEvent<?> event : key.pollEvents()) {
if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
continue;
}
Path parent = (Path) key.watchable();
Path p = parent.resolve((Path) event.context());
for (DirectoryModifiedListener listener : listeners) {
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE) {
// only do this if p referred to a file, not a directory
listener.onFileCreated(p);
}
}
}
My question is how to determine if the path p
referred to a deleted file or directory? Is this even possible with what the API exposes?
Files.isDirectory(path) is - as the name suggests - a realtime check.
The Path object (respectively, the implementation WindowsPath) itself has no state (or cached history). It's not much more than a placeholder for a path.
Therefore the sad answer is: you can't determine if a Path had referred to a directory or not after it was deleted.
One solution would be to remember the kind of the Path objects as long they exist. That means gather a list before start watching:
Path parent = Paths.get("/my/hotfolder");
Set<String> subdirs = new HashSet<String>();
for (Path p : Files.newDirectoryStream(parent)) {
if (Files.isDirectory(p))
subdirs.add(p.getFileName().toString());
}
Register ENTRY_CREATE to keep the list up to date
WatchKey key = hotfolder.register(watcher, ENTRY_CREATE, ENTRY_DELETE);
Now you can determine if a child object was a directory or not:
for (WatchEvent<?> event : key.pollEvents())
{
if (event.kind() == StandardWatchEventKinds.OVERFLOW)
continue;
Path p = ((Path) key.watchable()).resolve((Path) event.context());
String filename = p.getFileName().toString();
if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE && Files.isDirectory(p))
subdirs.add(filename);
if (event.kind() == StandardWatchEventKinds.ENTRY_DELETE)
{
if (subdirs.contains(filename))
{
for (DirectoryModifiedListener listener : listeners)
listener.onFileDeleted(p);
subdirs.remove(filename);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With