java 49 lines · 8 steps

Watching a directory with Java NIO

A small AutoCloseable wrapper around WatchService that reports file creates, modifies, and deletes as they happen.

Explained by highlit
1package com.example.fs;
2 
3import java.io.IOException;
4import java.nio.file.FileSystems;
5import java.nio.file.Path;
6import java.nio.file.StandardWatchEventKinds;
7import java.nio.file.WatchEvent;
8import java.nio.file.WatchKey;
9import java.nio.file.WatchService;
10 
11public class DirectoryWatcher implements AutoCloseable {
12 
13 private final Path directory;
14 private final WatchService watchService;
15 
16 public DirectoryWatcher(Path directory) throws IOException {
17 this.directory = directory;
18 this.watchService = FileSystems.getDefault().newWatchService();
19 directory.register(
20 watchService,
21 StandardWatchEventKinds.ENTRY_CREATE,
22 StandardWatchEventKinds.ENTRY_MODIFY,
23 StandardWatchEventKinds.ENTRY_DELETE);
24 }
25 
26 public void watch() throws InterruptedException {
27 while (true) {
28 WatchKey key = watchService.take();
29 for (WatchEvent<?> event : key.pollEvents()) {
30 WatchEvent.Kind<?> kind = event.kind();
31 if (kind == StandardWatchEventKinds.OVERFLOW) {
32 continue;
33 }
34 @SuppressWarnings("unchecked")
35 WatchEvent<Path> ev = (WatchEvent<Path>) event;
36 Path changed = directory.resolve(ev.context());
37 System.out.printf("%s -> %s%n", kind.name(), changed);
38 }
39 if (!key.reset()) {
40 break;
41 }
42 }
43 }
44 
45 @Override
46 public void close() throws IOException {
47 watchService.close();
48 }
49}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1WatchService turns filesystem changes into a blocking event stream you consume in a loop.
  2. 2Calling reset() after draining a WatchKey is mandatory — skip it and you stop receiving events.
  3. 3Implementing AutoCloseable lets try-with-resources guarantee the native watch handle is released.

Related explainers

java
@Component
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {
 

Transparent column encryption in Spring & JPA

encryption aes-gcm jpa-converter
Advanced 10 steps
java
package com.acme.billing.config;
 
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;

Feature-flagged beans with Spring @ConditionalOnProperty

feature-flags conditional-beans strategy-pattern
Intermediate 5 steps
java
public static Map<String, String> parseCookieHeader(String header) {
    Map<String, String> cookies = new LinkedHashMap<>();
    if (header == null || header.isBlank()) {
        return cookies;

Parsing an HTTP Cookie header in Java

string-parsing http url-decoding
Intermediate 6 steps
java
public class TimedSocketReader {
 
    private static final int READ_TIMEOUT_MS = 5_000;
    private static final int CONNECT_TIMEOUT_MS = 3_000;

Reading a socket with connect and read timeouts

sockets timeouts io
Intermediate 8 steps
java
public final class EncodingDetector {
 
    public enum Encoding {
        UTF_8, UTF_16LE, UTF_16BE, UTF_32LE, UTF_32BE, ASCII, UNKNOWN

Detecting text encoding from raw bytes in Java

byte-manipulation encoding-detection bitwise-operations
Intermediate 8 steps
java
public final class ImportOrganizer {
 
    private static final Pattern IMPORT_LINE =
            Pattern.compile("^import\\s+(static\\s+)?([\\w.]+(?:\\.\\*)?)\\s*;\\s*$");

Sorting Java imports with a regex pass

regex sorting text-processing
Intermediate 8 steps

Share this explainer

Here's the card — post it anywhere.

Watching a directory with Java NIO — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code