by Uwe Meding

Java 7 introduced some great additions to the standard API in the NIO packages that allow direct interaction with the underlying file system operations. The directory watcher service is one them. In general, we register a directory with a watcher service that sends us notifications in the form of keys. The mechanism is the somewhat analogous to the Selector/SelectionKey mechanism in java.nio package.
In this blog I am showing a way to implement a “tail -f” function in Java. There are three main steps to make the core functionality work:

1. Register the watcher serviceThe watcher service operates on the the directory containing the file we are interested in.


rootDir = file.getParent();
WatchService watcher = FileSystems.getDefault().newWatchService();
WatchKey regkey = rootDir.register(
watcher,
ENTRY_CREATE,
ENTRY_DELETE,
ENTRY_MODIFY);

2. Process the events from the watcher key
We continually process the watch events that the watcher service fires. Depending on the kind of change, we can now take different actions to process the file for example.


WatchKey key = watcher.take(); // or poll(…)
for (WatchEvent event : key.pollEvents()) {
WatchEvent.Kind kind = event.kind();
if (kind == ENTRY_MODIFY || kind == ENTRY_CREATE)
…process events…
}

3. Reset the key
This step is really important because as long as we are operating on a key, no more change events are generated by the system. Resetting the key tells the operating system that we are again interested in getting notified about any changes.


if (!key.reset()) {
break; // key in not usable anymore
}

Putting it all together

In my implementation I chose to make a FileFollowerStream a sub-class of the java.io.InputStream. Thus any usage follows the standard Java I/O coding patterns. The watcher service itself in implemented as a separated thread running in the background.

» (Java 7) Source Code:  github.com/umeding/FollowerStream

Leave a Reply