WatchEvent

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’s walkFileTree() static method with watch service.

5. Download Java Source Code

This was an example of java.nio.file.WatchEvent.

Download
You can download the full source code of this example here: WatchEventExample.zip

Prasad Saya

Prasad Saya is a software engineer with over ten years’ experience in application development, maintenance, testing and consulting on various platforms. He is a certified Java and Java EE developer. At present his interest is in developing Java applications. He also has experience working with databases and ERP applications.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Joe
Joe
6 years ago

What if you wanted to send the console messages to a text file for logging. How would this change the code?

Back to top button