0Pricing
Java Academy · Lektion

WatchService: Dateiänderungen überwachen

Registrieren Sie einen WatchService, um Ereignisse zum Erstellen, Ändern und Löschen von Dateien in Echtzeit zu erkennen.

WatchService: Dateiänderungen überwachen ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was ist WatchService?

WatchService überwacht ein Verzeichnis auf Dateisystemereignisse: Erstellung, Änderung und Löschung. Dazu verwendet es Benachrichtigungen auf Betriebssystemebene (inotify unter Linux, FSEvents unter macOS) – das ist deutlich effizienter als Polling.

import java.nio.file.*;

WatchService watcher = FileSystems.getDefault().newWatchService();
Path dir = Path.of("/home/user/watched");

dir.register(watcher,
    StandardWatchEventKinds.ENTRY_CREATE,
    StandardWatchEventKinds.ENTRY_MODIFY,
    StandardWatchEventKinds.ENTRY_DELETE
);
System.out.println("Watching: " + dir);

Ereignisse per Polling abfragen

Rufen Sie watcher.take() auf, um zu blockieren, bis ein Ereignis eintritt, und verarbeiten Sie anschließend die Ereignisse:

while (true) {
    WatchKey key;
    try {
        key = watcher.take(); // blocks until events arrive
    } catch (InterruptedException e) {
        break;
    }
    
    for (WatchEvent<?> event : key.pollEvents()) {
        WatchEvent.Kind<?> kind = event.kind();
        Path changed = ((WatchEvent<Path>) event).context();
        System.out.println(kind.name() + ": " + changed);
    }
    
    key.reset(); // must reset to receive further events
}

Nicht blockierendes Polling

Verwenden Sie watcher.poll() für nicht blockierende Prüfungen oder poll(timeout, unit) für zeitlich begrenztes Warten:

// Non-blocking — returns null if no events
WatchKey key = watcher.poll();
if (key != null) {
    // process events
    key.reset();
}

// Wait up to 5 seconds:
WatchKey key2 = watcher.poll(5, java.util.concurrent.TimeUnit.SECONDS);
if (key2 != null) {
    // process events
    key2.reset();
}

OVERFLOW-Ereignis

Wenn sich Ereignisse schneller ansammeln, als die Anwendung sie verarbeitet, signalisiert ein OVERFLOW-Ereignis, dass einige Ereignisse verloren gegangen sind. Behandeln Sie diesen Fall ordnungsgemäß:

for (WatchEvent<?> event : key.pollEvents()) {
    if (event.kind() == StandardWatchEventKinds.OVERFLOW) {
        System.out.println("OVERFLOW: some events missed, rescanning directory");
        // rescan dir to find current state
        continue;
    }
    // process normal events
}

Vollständiges funktionierendes Beispiel

Ein vollständiger Dateiüberwacher, der in einem Hintergrundthread ausgeführt wird:

class FileWatcher implements Runnable {
    private final WatchService watcher;
    
    FileWatcher(Path dir) throws IOException {
        watcher = FileSystems.getDefault().newWatchService();
        dir.register(watcher,
            StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_MODIFY,
            StandardWatchEventKinds.ENTRY_DELETE);
    }
    
    @Override
    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                WatchKey key = watcher.take();
                for (WatchEvent<?> e : key.pollEvents())
                    System.out.println(e.kind() + ": " + e.context());
                key.reset();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

Mehrere Verzeichnisse überwachen

Registrieren Sie mehrere Verzeichnisse beim selben WatchService. Verwenden Sie den zurückgegebenen WatchKey, um festzustellen, aus welchem Verzeichnis das Ereignis stammt:

Map<WatchKey, Path> keyMap = new HashMap<>();

for (Path dir : List.of(Path.of("/logs"), Path.of("/config"))) {
    WatchKey key = dir.register(watcher,
        StandardWatchEventKinds.ENTRY_MODIFY);
    keyMap.put(key, dir);
}

WatchKey key = watcher.take();
Path dir = keyMap.get(key);
System.out.println("Changed in: " + dir);

Vollständigen Pfad auflösen

Der von context() zurückgegebene Wert enthält nur den Dateinamen, nicht den vollständigen Pfad. Lösen Sie ihn gegen das überwachte Verzeichnis auf:

WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;
Path filename = pathEvent.context();
Path fullPath = watchedDir.resolve(filename);
System.out.println("Full path: " + fullPath);

Rekursive Verzeichnisüberwachung

WatchService überwacht nur das registrierte Verzeichnis, nicht dessen Unterverzeichnisse. Für eine rekursive Überwachung durchlaufen Sie den Verzeichnisbaum und registrieren jedes Unterverzeichnis:

WatchService watcher = FileSystems.getDefault().newWatchService();
Path root = Path.of("/project");

try (var stream = Files.walk(root)) {
    stream.filter(Files::isDirectory)
          .forEach(dir -> {
              try { dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE,
                  StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE);
              } catch (IOException e) { throw new RuntimeException(e); }
          });
}

Ressourcen freigeben

Schließen Sie den WatchService stets, wenn Sie fertig sind, um Betriebssystemressourcen freizugeben:

try (WatchService watcher = FileSystems.getDefault().newWatchService()) {
    Path dir = Path.of("/tmp/watch");
    dir.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
    
    WatchKey key = watcher.poll(10, java.util.concurrent.TimeUnit.SECONDS);
    if (key != null) {
        key.pollEvents().forEach(e -> System.out.println(e.context()));
        key.reset();
    }
} // watcher.close() called automatically

Praktischer Anwendungsfall: Hot-Reload der Konfiguration

Verwenden Sie WatchService, um die Konfiguration neu zu laden, wenn sich die Datei ändert:

class ConfigWatcher {
    private volatile Map<String, String> config = new HashMap<>();
    
    void loadConfig(Path file) throws IOException {
        config = Files.readAllLines(file).stream()
            .filter(l -> l.contains("="))
            .collect(Collectors.toMap(
                l -> l.split("=")[0].trim(),
                l -> l.split("=")[1].trim(),
                (a,b) -> b
            ));
    }
    
    // Call loadConfig again on ENTRY_MODIFY event
}

Einschränkungen von WatchService

Wichtige Einschränkungen:

  • Überwacht nur Verzeichnisse, keine einzelnen Dateien
  • Standardmäßig nicht rekursiv – jedes Unterverzeichnis muss manuell registriert werden
  • Unter macOS: verwendet intern Polling (weniger reaktionsschnell als inotify unter Linux)
  • Kann schnelle Änderungsbursts verpassen (OVERFLOW)
  • WatchKey wird ungültig, wenn das überwachte Verzeichnis gelöscht wird

Kurzer Test

Was müssen Sie nach der Verarbeitung von Ereignissen aus einem WatchKey aufrufen, bevor der WatchService weitere Ereignisse für diesen Schlüssel liefert?

Zusammenfassung: WatchService

Die wichtigsten Punkte:

  • Verzeichnisse für die Ereignisse ENTRY_CREATE/MODIFY/DELETE registrieren
  • take() blockiert; poll() ist nicht blockierend; poll(timeout, unit) wartet für eine bestimmte Zeit
  • Nach der Verarbeitung von Ereignissen stets key.reset() aufrufen
  • context() gibt nur den Dateinamen zurück – für den vollständigen Pfad gegen das überwachte Verzeichnis auflösen
  • WatchService mit try-with-resources schließen
  • Für eine rekursive Überwachung muss jedes Unterverzeichnis registriert werden

Häufig gestellte Fragen

Ist die Lektion „WatchService: Dateiänderungen überwachen“ kostenlos?

Ja — der vollständige Text von „WatchService: Dateiänderungen überwachen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „WatchService: Dateiänderungen überwachen“?

Registrieren Sie einen WatchService, um Ereignisse zum Erstellen, Ändern und Löschen von Dateien in Echtzeit zu erkennen. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Java Academy zu starten?

Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „WatchService: Dateiänderungen überwachen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?

Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Path: Dateipfade darstellen
  2. Files-Utility: Lesen, Schreiben, Kopieren, Verschieben
  3. Verzeichnisbäume mit Files.walk durchlaufen
  4. WatchService: Dateiänderungen überwachen
← Zurück zu Java Academy