java.nio.file.WatchEvent Example
WatchEvent<T>
is an interface defined in the java.nio.file
package. The type parameter T is the type of the context object associated with the event.
This interface has been in Java since Java SE 7 as part of NIO 2 File APIs. This is part of file change notification API, called the Watch Service API. Watch event in general represents an event or a repeated event for an object that is registered with a WatchService
. A watch service watches registered objects for changes and events.
In a file system, the watch service is used to register a directory (or directories) with the watch service. At the registration, the types of events of interest are specified, i.e., file creation, deletion, or modification. When the service detects an event of interest, it is forwarded to a process – a thread (or a pool of threads) – for watching any registered events. The event is handled as needed when it occurs.
1. Introduction
A watch event is classified by its kind. The kind()
method returns the event kind (an identifier), defined by WatchEvent.Kind<T>
interface. The StandardWatchEventKinds
class defines the standard event kinds.
The StandardWatchEventKinds
class has four fields (constants) that identify the event kinds: ENTRY_CREATE
, ENTRY_DELETE
, ENTRY_MODIFY
and OVERFLOW
. These identify the type of operation on a directory – an entry is created, deleted or modified in the directory. The overflow is a special event for lost or discarded events.
The events are of type WatchEvent.Kind<Path>
, except OVERFLOW
which is of type WatchEvent.Kind<Object>
.
This example shows how the watch events are used in a watch service application.
2. Watch Events
The example application watches a directory for changes by using watch service. The kind of events monitored are modify and delete; that the directory is modified (like adding a file to the directory) or a file is deleted from the directory.
The program is explained in the following steps:
2.1. Create a new watch service for the file system
WatchService watchService = FileSystems.getDefault().newWatchService();
Note the method throws IOException
.
2.2. Register for events to be monitored
Register one or more objects with the watch service. Any object that implements the Watchable
interface can be registered. The Path
extends the Watchable
, so the directory to be monitored is registered as a Path
object. Specify the type of events to monitor – in this case file modify and delete.
Path path = Paths.get("WatchedDir"); WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
A WatchKey
instance is returned for each directory registered. This is a token representing the registration of a Path
object with a watch service.
Note the directory being watched is an existing directory. The method throws IOException
.
2.3. Process the events
This is implemented as an infinite loop that waits for incoming events. When an event occurs, the watch key is signaled and placed into the watch service’s queue.
2.3.1. Wait for key to be signaled
The watch service’s take()
method returns a queued key. If no queued key is available, this method waits. The method throws InterruptedException
. This method’s usage is shown in the following code snippet.
for (;;) { // infinite loop WatchKey key; try { System.out.println("Waiting for key to be signalled..."); key = watchService.take(); } catch (InterruptedException ex) { … }
NOTE: There is also a poll()
method which returns a queued key, if available. This method returns immediately with a null
value, if key is unavailable.
2.3.2. Process the pending events for the key
The watch key’s pollEvents()
method retrieves and removes all pending events for this watch key. The method returns a List
collection of the events that are retrieved.
List<WatchEvent<?>> eventList = key.pollEvents(); System.out.println("Process the pending events for the key: " + eventList.size()); for (WatchEvent<?> genericEvent : key.pollEvents()) {
The List
collection is iterated to process the events.
2.3.3. Retrieve the type of event
For each event the watch event’s kind()
method returns the type of event. If the event is an OVERFLOW
, the event is discarded and the program continues processing the next event.
NOTE: No matter what events the key has registered for, it is possible to receive an overflow event.
WatchEvent.Kind<?> eventKind = genericEvent.kind(); if (eventKind == OVERFLOW) { continue; // pending events for loop }
2.3.4. Retrieve the file path associated with the event
The watch event’s context()
method returns the Path
object associated with the event. The path is the relative path between the directory registered with the watch service, and the entry that is created, deleted, or modified.The file’s path information can be used to do something – for example print the file name.
WatchEvent pathEvent = (WatchEvent) genericEvent; Path file = pathEvent.context(); System.out.println(" File name: " + file.toString());
2.3.5. Reset the key
The events for the key have been processed, and it is required to put the key back into a ready state by invoking watch key’s reset()
method. If this method returns false, the key is no longer valid and the infinite loop exits.
boolean validKey = key.reset(); if (! validKey) { break; // infinite for loop }
2.4. Close the service
The watch service exits when either the thread exits or when it is closed by invoking its close()
method. The method throws IOException
.
watchService.close();
3. The Example
The following is the complete code for the watch event example.
WatchEventExample.java
import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.FileSystems; import java.nio.file.WatchService; import java.nio.file.WatchKey; import java.nio.file.WatchEvent; import java.nio.file.WatchEvent.Kind; import java.io.IOException; import static java.nio.file.StandardWatchEventKinds.*; import java.util.List; public class WatchEventExample { public static void main(String [] args) throws Exception { new WatchEventExample().doWatch(); } @SuppressWarnings("unchecked") private void doWatch() throws IOException, InterruptedException { WatchService watchService = FileSystems.getDefault().newWatchService(); Path path = Paths.get("WatchedDir"); WatchKey watchKey = path.register(watchService, ENTRY_DELETE, ENTRY_MODIFY); System.out.println("Watch service registered dir: " + path.toString()); for (;;) { WatchKey key; try { System.out.println("Waiting for key to be signalled..."); key = watchService.take(); } catch (InterruptedException ex) { System.out.println("Interrupted Exception"); return; } List<WatchEvent<?>> eventList = key.pollEvents(); System.out.println("Process the pending events for the key: " + eventList.size()); for (WatchEvent<?> genericEvent: eventList) { WatchEvent.Kind<?> eventKind = genericEvent.kind(); System.out.println("Event kind: " + eventKind); if (eventKind == OVERFLOW) { continue; // pending events for loop } WatchEvent pathEvent = (WatchEvent) genericEvent; Path file = pathEvent.context(); System.out.println("File name: " + file.toString()); } boolean validKey = key.reset(); System.out.println("Key reset"); System.out.println(""); if (! validKey) { System.out.println("Invalid key"); break; // infinite for loop } } // end infinite for loop watchService.close(); System.out.println("Watch service closed."); } }
4. Run the Example
This program is tested on Windows 7 operating system. Note that Java 7 is required. Follow the below steps to run the example program and observe the results.
4.1. Create a directory:
Create a new directory in the same directory as the program: WatchedDir
. Initially the directory can be empty.
4.2. Run the program:
Run the program from OS command prompt:
> java WatchEventExample
The following output is displayed on the terminal:
Watch service registered dir: WatchedDir Waiting for key to be signaled...
From the output:
- Watch service registered dir: WatchedDir. This is the relative path of the monitored directory. Note the directory is watched for modify and delete events.
- Waiting for key to be signaled…The application (infinite loop) waits for the first activity in the monitored directory.
4.3. Modify events:
From the Windows file manager copy (drag and drop) a file (for example, notes.txt) into the WatchedDir
. Note the following output is displayed on the terminal immediately:
Process the pending events for the key: 1 Event kind: ENTRY_MODIFY File name: notes.txt Key reset Waiting for key to be signaled...
From the output:
- Process the pending events for the key: 1. This is the number of events generated and retrieved from the watch key. This happened when the file is copied to the directory.
- Event kind: ENTRY_MODIFY. The returned value from the watch event’s
kind()
method. The directory contents are changed. - File name: notes.txt. The file name associated with the path returned from the event’s
context()
method. - Key reset. The watch key is reset and is further checked if valid.
- Waiting for key to be signaled… The application (infinite loop) waits for the next directory activity and events in the monitored directory.
4.4. Delete events:
From the Windows file manager navigate into the WatchedDir
directory. Delete a file from the directory contents (for example, notes.txt). Note the following output is displayed on the terminal immediately:
Process the pending events for the key: 1 Event kind: ENTRY_DELETE File name: notes.txt Key reset Waiting for key to be signaled....
The output is similar to that of the modify event. From the output note the number of events, the delete event type and the file name.
4.5. Close the program:
The program waits infinitely. Terminate the program with CTRL + C
.
NOTES
- Further, the program may be tested with various file actions within the directory. Some of them are save a new file into the directory, make a copy of a file existing in the directory, rename a file, edit an existing file and save it, etc. Observe the number of events and the event kinds for each file action. For some file actions there are more than one event.
- The present example monitors a directory with files. To monitor a file tree, use the
Files
class’swalkFileTree()
static method with watch service.
5. Download Java Source Code
This was an example of java.nio.file.WatchEvent.
You can download the full source code of this example here: WatchEventExample.zip
What if you wanted to send the console messages to a text file for logging. How would this change the code?