WatchService: Monitoramento de Alterações em Arquivos
Registre um WatchService para detectar em tempo real eventos de criação, modificação e exclusão de arquivos.
WatchService: Monitoramento de Alterações em Arquivos é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
O que é WatchService?
WatchService monitors a directory for file system events: creation, modification, and deletion. It uses OS-level notifications (inotify on Linux, FSEvents on macOS) — much more efficient than 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);Consulta periódica de eventos
Chame watcher.take() para bloquear até que ocorra um evento e, então, processe os eventos:
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
}Consulta sem bloqueio
Use watcher.poll() para verificações sem bloqueio ou poll(timeout, unit) para esperas cronometradas:
// 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();
}Evento OVERFLOW
Se os eventos se acumularem mais rapidamente do que a aplicação consegue processá-los, um evento OVERFLOW sinalizará que alguns eventos foram perdidos. Trate essa situação adequadamente:
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
}Exemplo completo em funcionamento
Um observador completo de arquivos executado em uma thread em segundo plano:
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();
}
}
}
}Observação de vários diretórios
Registre vários diretórios com o mesmo WatchService. Use o WatchKey retornado para identificar de qual diretório veio o evento:
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);Resolução do caminho completo
O context() do evento retorna apenas o nome do arquivo, não o caminho completo. Resolva-o em relação ao diretório observado:
WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;
Path filename = pathEvent.context();
Path fullPath = watchedDir.resolve(filename);
System.out.println("Full path: " + fullPath);Observação recursiva de diretórios
WatchService observa apenas o diretório registrado, não os respectivos subdiretórios. Para fazer uma observação recursiva, percorra a árvore e registre cada subdiretório:
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); }
});
}Limpeza de recursos
Sempre feche o WatchService ao terminar para liberar os recursos do OS:
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 automaticallyCaso prático: recarregamento imediato da configuração
Use WatchService para recarregar a configuração quando o arquivo for alterado:
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
}Limitações do WatchService
Limitações importantes:
- Observa apenas diretórios, não arquivos individuais
- Não é recursivo por padrão: registre cada subdiretório manualmente
- No macOS: usa consulta periódica internamente, sendo menos responsivo que o inotify do Linux
- Pode não detectar rajadas rápidas de alterações (
OVERFLOW) - WatchKey se torna inválido se o diretório observado for excluído
Verificação rápida
Depois de processar os eventos de um WatchKey, o que você deve chamar antes que o WatchService entregue novos eventos para essa chave?
Recapitulação: WatchService
Principais conclusões:
- Registre diretórios com eventos ENTRY_CREATE/MODIFY/DELETE
take()bloqueia;poll()não bloqueia; usepoll(timeout, unit)para uma espera cronometrada- Sempre chame
key.reset()depois de processar os eventos context()retorna apenas o nome do arquivo; resolva-o em relação ao diretório observado para obter o caminho completo- Feche o WatchService usando try-with-resources
- A observação recursiva exige o registro de cada subdiretório
Perguntas Frequentes
A aula “WatchService: Monitoramento de Alterações em Arquivos” é grátis?
Sim — o texto completo de “WatchService: Monitoramento de Alterações em Arquivos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “WatchService: Monitoramento de Alterações em Arquivos”?
Registre um WatchService para detectar em tempo real eventos de criação, modificação e exclusão de arquivos. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “WatchService: Monitoramento de Alterações em Arquivos”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Path: Representação de Locais de Arquivos
- Utilitário Files: Ler, Escrever, Copiar e Mover
- Percurso de Árvores de Diretórios com Files.walk
- WatchService: Monitoramento de Alterações em Arquivos