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 automaticallyPraktischer 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
- Path: Dateipfade darstellen
- Files-Utility: Lesen, Schreiben, Kopieren, Verschieben
- Verzeichnisbäume mit Files.walk durchlaufen
- WatchService: Dateiänderungen überwachen