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.
[the_ad id=”644″]
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.WatchServiceobject. 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()wherepathis an object of typejava.nio.file.Pathand refers to the path of directory which we are monitoring. Thus, if we are using second approach, we need to create ajava.nio.file.Pathobject 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
registermethod 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 usingpollEventsmethod ofWatchKey. AWatchKeycan be created by callingpollortakemethod on watcher object. Difference betweenpollandtakemethods is thatpollreturnsnullif the event is not detected at the time when this method is called whiletakemethod 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.Watchableinterface can be registered. Sincejava.nio.file.Pathimplements 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
OVERFLOWevent to occur. This event indicates that some events may have lost or discarded. registermethod also returns a watch key but we should use the watch key returned bytakeorpollmethods 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.StandardWatchEventKindsclass as constants. This is afinalclass.