Today I’ve started to experiment with some new features we have in Java 7. First is the file system WatchService
which allows us to listen to changes in a directory without any pooling. Looks really great. You just register to be notified about changes and wait to get your notifications. The best part of it is, you can assign as much listeners as you like and even from different threads, with no code changes, it is all thread safe. Here’s what I’ve done to get notified about files being modified/removed/added to my very important TEMP directory:
public class PathTest {
private static void listenForChanges(File file) throws IOException {
Path path = file.toPath();
if (file.isDirectory()) {
WatchService ws = path.getFileSystem().newWatchService();
path.register(ws, StandardWatchEventKind.ENTRY_CREATE,
StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY);
WatchKey watch = null;
while (true) {
System.out.println("Watching directory: " + file.getPath());
try {
watch = ws.take();
} catch (InterruptedException ex) {
System.err.println("Interrupted");
}
List<WatchEvent<?>> events = watch.pollEvents();
watch.reset();
for (WatchEvent<?> event : events) {
Kind<Path> kind = (Kind<Path>) event.kind();
Path context = (Path) event.context();
if (kind.equals(StandardWatchEventKind.OVERFLOW)) {
System.out.println("OVERFLOW");
} else if (kind.equals(StandardWatchEventKind.ENTRY_CREATE)) {
System.out.println("Created: " + context.getFileName());
} else if (kind.equals(StandardWatchEventKind.ENTRY_DELETE)) {
System.out.println("Deleted: " + context.getFileName());
} else if (kind.equals(StandardWatchEventKind.ENTRY_MODIFY)) {
System.out.println("Modified: " + context.getFileName());
}
}
}
} else {
System.err.println("Not a directory. Will exit.");
}
}
public static void main(String[] args) {
if (args.length > 0) {
File file = new File(args[0]);
try {
System.out.println("Listening on: " + file);
listenForChanges(file);
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
System.out.println("Pass directory path as parameter");
}
}
}
There is one tricky thing when using WatchService
. You have to remember to reset the WatchKey
after you poll events, or it will stop getting updates (only first directory change will execute your code, rest won’t do anything).