The javadoc for StandardWatchEventKinds.ENTRY_MODIFY says:
Directory entry modified. When a directory is registered for this event the
If you use RxJava you can use the operator throttleLast. In the example below only the last event in 1000 milliseconds is emitted for each file in the watched directory.
public class FileUtils {
private static final long EVENT_DELAY = 1000L;
public static Observable watch(Path directory, String glob) {
return Observable.create(subscriber -> {
final PathMatcher matcher = directory.getFileSystem().getPathMatcher("glob:" + glob);
WatchService watcher = FileSystems.getDefault().newWatchService();
subscriber.setCancellable(watcher::close);
try {
directory.register(watcher,
ENTRY_CREATE,
ENTRY_DELETE,
ENTRY_MODIFY);
} catch (IOException e) {
subscriber.onError(e);
return;
}
while (!subscriber.isDisposed()) {
WatchKey key;
try {
key = watcher.take();
} catch (InterruptedException e) {
if (subscriber.isDisposed())
subscriber.onComplete();
else
subscriber.onError(e);
return;
}
for (WatchEvent> event : key.pollEvents()) {
WatchEvent.Kind> kind = event.kind();
if (kind != OVERFLOW) {
WatchEvent ev = (WatchEvent) event;
Path child = directory.resolve(ev.context());
if (matcher.matches(child.getFileName()))
subscriber.onNext(new FileWatchEvent(kindToType(kind), child));
}
}
if (!key.reset()) {
subscriber.onError(new IOException("Invalid key"));
return;
}
}
}).groupBy(FileWatchEvent::getPath).flatMap(o -> o.throttleLast(EVENT_DELAY, TimeUnit.MILLISECONDS));
}
private static FileWatchEvent.Type kindToType(WatchEvent.Kind kind) {
if (StandardWatchEventKinds.ENTRY_CREATE.equals(kind))
return FileWatchEvent.Type.ADDED;
else if (StandardWatchEventKinds.ENTRY_MODIFY.equals(kind))
return FileWatchEvent.Type.MODIFIED;
else if (StandardWatchEventKinds.ENTRY_DELETE.equals(kind))
return FileWatchEvent.Type.DELETED;
throw new RuntimeException("Invalid kind: " + kind);
}
public static class FileWatchEvent {
public enum Type {
ADDED, DELETED, MODIFIED
}
private Type type;
private Path path;
public FileWatchEvent(Type type, Path path) {
this.type = type;
this.path = path;
}
public Type getType() {
return type;
}
public Path getPath() {
return path;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileWatchEvent that = (FileWatchEvent) o;
if (type != that.type) return false;
return path != null ? path.equals(that.path) : that.path == null;
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (path != null ? path.hashCode() : 0);
return result;
}
}
}