I want to watch (monitor) multiple directories using Java NIO WatchService
.
My problem here is the number of directories to watch is dynamic and the user can add any number of directories to the WatchService
. Is this achievable?
It is possible to register multiple paths with the same WatchService
. Each path gets its own WatchKey
. The take()
or poll()
will then return the WatchKey
corresponding to the path that was modified.
See Java's WatchDir example for details.
Following the same link as in previous answers: Oracle WatchDir.
You can create first the WatchService
:
WatchService watchService = FileSystems.getDefault().newWatchService();
At this point you can add many paths to the same WatchService
:
Path path1 = Paths.get("full\path\1\\");
path1.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE);
Path path2 = Paths.get("full\path\2\\");
path2.register(watchService,
StandardWatchEventKinds.ENTRY_CREATE);
Then you can manage the events as follow:
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println(
"Event kind:" + event.kind()
+ ". File affected: " + event.context() + ".");
}
key.reset();
}
Now, if you want to get more information about where was raised the event, you can create a map to link the key and the path by example (You can consider create the variable as class level following your needs):
Map<WatchKey, Path> keys;
In this example you can have the paths inside a list, then you need to loop into it and add each path to the same WatchService
:
for (Path path : paths) {
WatchKey key = path.register(
watchService,
StandardWatchEventKinds.ENTRY_CREATE);
keys.put(key, path);
}
Now to manage the events, you can add something like it:
WatchKey key;
while ((key = watchService.take()) != null) {
Path path = keys.get(key);
// More code here.
key.reset();
}
I am just trying to explain how exactly this can be done using WatchService
.
Here is a piece of code that illustrates how you can use one WatchService
instance and listen to two Paths
this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<>();
Path plugins = Paths.get(INSTANCE.getPluginPath());
logger.info(String.format("Scanning %s ...", plugins));
registerAll(plugins);
Path drivers = Paths.get(INSTANCE.getDriverPath());
logger.info(String.format("Scanning %s ...", drivers));
registerAll(drivers);
The example is based on Oracle Example
adding a complete simple solution for a few fixed directories. This example has 3 directories that will be monitored and when a file is created i am looking for, i will process it. Using this approach in Linux instead of a port listener which i need root access.
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 java.io.File;
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.WatchKey;
import java.nio.file.WatchService;
import java.util.HashMap;
import java.util.Map;
public class WatchDirSimple {
public static void main(String[] args) {
try {
WatchService watcher = FileSystems.getDefault().newWatchService();
Map<WatchKey,Path> keys = new HashMap<WatchKey,Path>();
WatchDirSimple watchDirSimple = new WatchDirSimple();
WatchKey key;
Path dir;
dir = Paths.get(System.getProperty("user.home")+File.separator + "Documents\\PROD_Data\\ODBI");
key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
dir = Paths.get(System.getProperty("user.home")+File.separator + "Documents\\PROD_Data\\ODBI\\@fred");
key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
dir = Paths.get(System.getProperty("user.home")+File.separator + "Documents\\PROD_Data\\ODBI\\CMODupgrade");
key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
keys.put(key, dir);
for (;;) {
try {
key = watcher.take();
} catch (InterruptedException x) {
return;
}
dir = keys.get(key);
if (dir == null) {
System.err.println("WatchKey not recognized!!");
continue;
}
for (WatchEvent<?> event: key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
// Context for directory entry event is the file name of entry
WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path name = ev.context();
Path child = dir.resolve(name);
// print out event
System.out.format("%s: %s\n", event.kind().name(), child);
}
// reset key and remove from set if directory no longer accessible
boolean valid = key.reset();
if (!valid) {
keys.remove(key);
// all directories are inaccessible
if (keys.isEmpty()) {
break;
}
}
}
watchDirSimple.register(dir, watcher, keys);
} catch (IOException e) {
e.printStackTrace();
}
}
}
© 2022 - 2024 — McMap. All rights reserved.