Three Java Ways to Dynamically Monitor File Changes: Polling, WatchService, and Commons‑IO

To handle dynamic file changes such as rule updates, configuration reloads, or log monitoring, this article compares three Java approaches—simple polling with File#lastModified, the OS‑integrated WatchService API, and the Apache Commons‑IO monitor—detailing their implementations, advantages, drawbacks, and practical usage tips.

Senior Brother's Insights
Senior Brother's Insights
Senior Brother's Insights
Three Java Ways to Dynamically Monitor File Changes: Polling, WatchService, and Commons‑IO

Background

When rules or configuration files are stored as files, an application often needs to detect changes and reload them. The same requirement appears in scenarios such as dynamic configuration reload, log file monitoring, or FTP file change detection.

Solution 1: Scheduled Task + File#lastModified

The simplest approach is to run a periodic task that reads File.lastModified() and compares it with the previous timestamp. If the value differs, the file has been modified and the application can reload it.

public class FileWatchDemo {
    public static long LAST_TIME = 0L;
    public static void main(String[] args) throws IOException {
        String fileName = "/Users/zzs/temp/1.txt";
        createFile(fileName);
        for (int i = 0; i < 2; i++) {
            long timestamp = readLastModified(fileName);
            if (timestamp != LAST_TIME) {
                System.out.println("文件已被更新:" + timestamp);
                LAST_TIME = timestamp;
                // reload file content
            } else {
                System.out.println("文件未更新");
            }
        }
    }
    public static void createFile(String fileName) throws IOException {
        File file = new File(fileName);
        if (!file.exists()) {
            boolean result = file.createNewFile();
            System.out.println("创建文件:" + result);
        }
    }
    public static long readLastModified(String fileName) {
        File file = new File(fileName);
        return file.lastModified();
    }
}

This method works for low‑frequency file changes but incurs overhead from repeated polling and state comparison. It also suffers from known bugs in File#lastModified on Java 8/9.

Solution 2: WatchService

Java 7 introduced java.nio.file.WatchService, an OS‑level file system monitor that can watch directories for creation, deletion, and modification events without manual polling.

public class WatchServiceDemo {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("/Users/zzs/temp/");
        WatchService watcher = FileSystems.getDefault().newWatchService();
        path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
        try {
            while (true) {
                WatchKey key = watcher.take();
                for (WatchEvent<?> event : key.pollEvents()) {
                    if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
                        continue;
                    }
                    Path fileName = (Path) event.context();
                    System.out.println("文件更新: " + fileName);
                }
                if (!key.reset()) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Supported event kinds include:

ENTRY_CREATE – file created

ENTRY_DELETE – file deleted

ENTRY_MODIFY – file modified

OVERFLOW – events lost

Internally, WatchService runs a dedicated thread (e.g., PollingWatchService) that polls the OS at a configurable interval. The default sensitivity levels are defined in SensitivityWatchEventModifier (HIGH = 2 s, MEDIUM = 10 s, LOW = 30 s) and can be passed when registering the path.

path.register(watcher, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY},
    SensitivityWatchEventModifier.HIGH);

Advantages: no manual polling, higher efficiency. Drawbacks: only monitors a single directory (no recursive sub‑directory watching), and the notification latency is limited to the chosen sensitivity interval.

Solution 3: Apache Commons‑IO

Commons‑IO provides a ready‑made file‑monitoring framework in the org.apache.commons.io.monitor package.

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.7</version>
</dependency>

Typical usage steps:

Create a listener by extending FileAlterationListenerAdaptor and override methods for create, modify, delete events.

Instantiate a FileAlterationObserver for the target directory (optionally with a filter).

Attach the observer to a FileAlterationMonitor with a polling interval.

Start the monitor.

public class FileListener extends FileAlterationListenerAdaptor {
    @Override
    public void onFileCreate(File file) {
        System.out.println("新建:" + file.getAbsolutePath());
        // TODO: reload file content
    }
    @Override
    public void onFileChange(File file) {
        System.out.println("修改:" + file.getAbsolutePath());
    }
    @Override
    public void onFileDelete(File file) {
        System.out.println("删除:" + file.getAbsolutePath());
    }
    // other callbacks omitted for brevity
}
public class FileMonitor {
    private FileAlterationMonitor monitor;
    public FileMonitor(long interval) {
        monitor = new FileAlterationMonitor(interval);
    }
    public void monitor(String path, FileAlterationListener listener) {
        FileAlterationObserver observer = new FileAlterationObserver(new File(path));
        monitor.addObserver(observer);
        observer.addListener(listener);
    }
    public void start() throws Exception { monitor.start(); }
    public void stop() throws Exception { monitor.stop(); }
}
public class FileRunner {
    public static void main(String[] args) throws Exception {
        FileMonitor fileMonitor = new FileMonitor(1000);
        fileMonitor.monitor("/Users/zzs/temp/", new FileListener());
        fileMonitor.start();
    }
}

Running the demo prints log messages each second; when a file changes, the corresponding event method is invoked. The polling interval can be adjusted when constructing FileMonitor. Filters can be applied via the observer’s constructor to watch only specific files.

Conclusion

All three Java‑based file‑watching techniques have trade‑offs. Simple polling is easy but inefficient; WatchService offers OS‑level efficiency but limited to a single directory and coarse latency; Commons‑IO provides a flexible, configurable solution with built‑in filtering. Choose the approach that best matches your application’s performance requirements and directory‑structure complexity.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavafile I/OFile MonitoringWatchServiceCommons-IO
Senior Brother's Insights
Written by

Senior Brother's Insights

A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.