Monitoring directory : Meaning & Reason
Monitoring a directory or a folder means keeping a watch on that directory for events such as a new file created, a file removed or modified. A typical requirement for such monitoring would be to implement an auto refresh functionality where you show the contents of a folder. With active monitoring on a folder, you can display the accurate list of files when the directory contents are modified in the background.
How to Monitor a directory in Java
Java 7 introduced java.nio package
which provides support for monitoring a directory for changes. It allows us to create a service which watches a directory for any modifications in its contents. The directory is required to be registered with a service so that the service is notified whenever the event(for which the directory was registered) occurs.
Implementation steps
Let’s go to action and write the code to monitor a directory. First, we shall outline the steps which are required for this. Our code will also follow the same sequence of steps.
- First step is to create a
java.nio.file.WatchService
object. This object can be created in 2 ways: from the default file system of the machine on which java is running(using the codeFileSystems.getDefault().newWatchService()
) or using the object of directory which we wish to monitor. Second approach uses the codepath.getFileSystem().newWatchService()
wherepath
is an object of typejava.nio.file.Path
and refers to the path of directory which we are monitoring. Thus, if we are using second approach, we need to create ajava.nio.file.Path
object first.
We shall use this approach in our code. - Second step is to register the directory with the watch service which we created above for the events we want to detect. Events may be file creation, deletion or modification. This is done using
register
method which takes the watch service and event types are arguments. - Creating a watch key which is an object of type
java.nio.file.WatchKey
. This key receives the notification when an event occurs. These events can be retrieved usingpollEvents
method ofWatchKey
. AWatchKey
can be created by callingpoll
ortake
method on watcher object. Difference betweenpoll
andtake
methods is thatpoll
returnsnull
if the event is not detected at the time when this method is called whiletake
method goes in waiting state if the event is not detected at the time when it is called. - Finally, when you get the list of events, you can check for the kind of event(create, delete, modify) and take the appropriate action if this is the event you are interested in.
Now, we shall translate the above algorithm into code. Read code comments to get a better understanding of the concept.
import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.util.List; import java.util.UUID; public class DirectoryWatcher { public static void main(String[] args) { // get path object pointing to the directory we wish to monitor Path path = Paths.get("E:\\codippa"); try { // get watch service which will monitor the directory WatchService watcher = path.getFileSystem().newWatchService(); // associate watch service with the directory to listen to the event // types path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE); System.out.println("Monitoring directory for changes..."); // listen to events WatchKey watchKey = watcher.take(); // get list of events as they occur List<WatchEvent<?>> events = watchKey.pollEvents(); //iterate over events for (WatchEvent event : events) { //check if the event refers to a new file created if (event.kind() == StandardWatchEventKinds.ENTRY_CREATE) { //print file name which is newly created System.out.println("Created: " + event.context().toString()); } } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }
path.register(watcher, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY);
Explanation & Output
As you can see, the above code is based on exact same steps which we outlined in the algorithm before the code snippet. The program is monitoring a folder “E:\\codippa” on the Windows filesystem. This is created as a java.nio.file.Path
object using static get method of java.nio.file.Paths
class. Before executing the program, the contents of the folder were as below:
When the program is executed, it keeps on listening for events on the specified folder. Following is the output of the program when a file is added to this folder as shown in the image below:
Monitoring directory for changes…
Created: Readme.txt
Note that the above program will terminate as soon as a file is created in the designated folder. If you want to listen for events forever, then surround the code starting from watcher.take()
statement inside an infinite loop. Also, the above code will block till a create event occurs. So, if don’t want it to block then execute this code inside a new thread.
Let’s tweak in
- Only an object which is watchable can be registered with a Watch Service. This means that only an object which implements
java.nio.file.Watchable
interface can be registered. Sincejava.nio.file.Path
implements this interface, it can be registered with a Watch Service. - A watch key can be used by multiple threads at the same time.
- No matter what kind of events you have registered for listening, there are chances for an
OVERFLOW
event to occur. This event indicates that some events may have lost or discarded. register
method also returns a watch key but we should use the watch key returned bytake
orpoll
methods to read and iterate over the events. Same has been done in the above example.- Types of events that can be monitored are defined in
java.nio.file.StandardWatchEventKinds
class as constants. This is afinal
class.