javaintermediate

Java File Watcher — Directory Monitoring

Watch directories for file changes using WatchService: create, modify, delete events with filtering.

java
import java.nio.file.*;
import java.io.IOException;
import java.util.concurrent.*;

public class FileWatcher {

    public static void watch(String directory, FileChangeHandler handler)
            throws IOException, InterruptedException {
        WatchService watcher = FileSystems.getDefault().newWatchService();
        Path dir = Path.of(directory);

        dir.register(watcher,
            StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY,
            StandardWatchEventKinds.ENTRY_DELETE);

        System.out.println("Watching: " + dir.toAbsolutePath());

        while (true) {
            WatchKey key = watcher.take(); // blocks until event

            for (WatchEvent<?> event : key.pollEvents()) {
                WatchEvent.Kind<?> kind = event.kind();

                if (kind == StandardWatchEventKinds.OVERFLOW) continue;

                @SuppressWarnings("unchecked")
                WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;
                Path filename = pathEvent.context();
                Path fullPath = dir.resolve(filename);

                handler.onChange(kind.name(), fullPath);
            }

            if (!key.reset()) {
                System.out.println("Watch key invalid, exiting");
                break;
            }
        }
    }

    @FunctionalInterface
    interface FileChangeHandler {
        void onChange(String eventType, Path path);
    }

    // Auto-reload config on change
    public static void watchConfig(Path configFile, Runnable onReload) {
        var executor = Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r, "config-watcher");
            t.setDaemon(true);
            return t;
        });

        executor.submit(() -> {
            try {
                watch(configFile.getParent().toString(), (event, path) -> {
                    if (path.getFileName().equals(configFile.getFileName())
                        && event.equals("ENTRY_MODIFY")) {
                        System.out.println("Config changed, reloading...");
                        onReload.run();
                    }
                });
            } catch (Exception e) {
                System.err.println("Watcher error: " + e.getMessage());
            }
        });
    }

    public static void main(String[] args) throws Exception {
        watch("/tmp/watched", (event, path) ->
            System.out.printf("[%s] %s%n", event, path));
    }
}

Use Cases

  • Auto-reloading configuration files
  • File sync and upload triggers
  • Development hot-reload utilities

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.