WatchService in Java

Naveen AnamaneniUpdated · 3 min read
mediumJava 25javafilesnio

The WatchService API in Java, in java.nio.file, lets a program watch a folder and be told when files in it are created, modified or deleted. It is used for things like reloading a configuration file when it changes, processing files dropped into an "inbox" folder, or refreshing a file list in an editor. You register a folder with a watch service, then wait for watch keys that carry the events. In this lesson, you will learn the steps and build a small inbox watcher.

Steps

  1. Create a watch service: FileSystems.getDefault().newWatchService().
  2. Register a folder for event kinds: dir.register(watcher, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE).
  3. Wait for a key: watcher.take() (waits forever) or watcher.poll(timeout, unit).
  4. Read its events: key.pollEvents(); each event has a kind() and a context() (the file name).
  5. Call key.reset() so the key can report more events.

Event Kinds

KindMeaning
ENTRY_CREATEA file or folder was created or moved in
ENTRY_MODIFYA file's contents or attributes changed
ENTRY_DELETEA file or folder was deleted or moved out
OVERFLOWEvents were lost because too many happened at once

Example: Watching an Inbox Folder

Let's see an example that watches a folder and reacts when a file appears. On some systems, such as macOS, the JDK checks folders every few seconds, so the event can take a moment to arrive.

InboxWatcher.java▶ Try it
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.concurrent.TimeUnit;
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
 
public class InboxWatcher {
    public static void main(String[] args)
            throws IOException, InterruptedException {
        Path inbox = Files.createDirectories(Path.of("inbox"));
 
        try (WatchService watcher =
                FileSystems.getDefault().newWatchService()) {
            inbox.register(watcher, ENTRY_CREATE);
            System.out.println("Watching " + inbox);
 
            Files.writeString(inbox.resolve("navika-homework.txt"), "done");
 
            WatchKey key = watcher.poll(15, TimeUnit.SECONDS);
            if (key == null) {
                System.out.println("No events in time");
                return;
            }
            for (WatchEvent<?> event : key.pollEvents()) {
                if (event.kind() == ENTRY_CREATE) {
                    Path name = (Path) event.context();
                    System.out.println("New file: " + name + " ("
                        + Files.size(inbox.resolve(name)) + " bytes)");
                }
            }
            key.reset();
        }
    }
}
Output
Watching inbox
New file: navika-homework.txt (4 bytes)

Explanation: The inbox folder is registered for ENTRY_CREATE events. When a file is written into it, the watch service queues a key. poll waits up to 15 seconds for it. Each event's context() is the file's name relative to the folder, so inbox.resolve(name) gives its full path. A real watcher would loop, calling take() and reset() forever.

Watching Folder Trees

Common Mistakes

Forgetting key.reset(). The key stops reporting events.

Treating the context as a full path. Resolve it against the watched folder.

Expecting events from subfolders. Register them too.

Practice

  1. Easy: Watch a folder and print every create, modify and delete event until a file named stop is created.
  2. Harder: Write an inbox processor that moves every new .csv file into a processed folder after printing its number of lines.

Quick check: WatchService

4 questions
1How do you start watching a folder?
2What does event.context() return?
3What happens if you forget key.reset()?
4Does a watch service report changes in subfolders?

Key Takeaways

Was this tutorial helpful?

Lesson 369 of 482