Created
February 23, 2022 21:14
-
-
Save mherman22/4c2a6b423d0e72c83507e733ce0935ff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.nio.file.*; | |
import static java.nio.file.StandardWatchEventKinds.*; | |
import static java.nio.file.LinkOption.*; | |
import java.nio.file.attribute.*; | |
import java.io.*; | |
import java.util.*; | |
/** | |
* watching a directory for changes to files. | |
*/ | |
public class WatchDir { | |
private final WatchService watcher; | |
private final Map<WatchKey,Path> keys; | |
private final boolean recursive; | |
private boolean trace = false; | |
@SuppressWarnings("unchecked") | |
static <T> WatchEvent<T> cast(WatchEvent<?> event) { | |
return (WatchEvent<T>)event; | |
} | |
/** | |
* Register the given directory with the WatchService | |
*/ | |
private void register(Path dir) throws IOException { | |
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); | |
if (trace) { | |
Path prev = keys.get(key); | |
if (prev == null) { | |
System.out.format("register: %s\n", dir); | |
} else { | |
if (!dir.equals(prev)) { | |
System.out.format("update: %s -> %s\n", prev, dir); | |
} | |
} | |
} | |
keys.put(key, dir); | |
} | |
/** | |
* Register the given directory, and all its sub-directories, with the | |
* WatchService. | |
*/ | |
private void registerAll(final Path start) throws IOException { | |
// register directory and sub-directories | |
Files.walkFileTree(start, new SimpleFileVisitor<Path>() { | |
@Override | |
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) | |
throws IOException | |
{ | |
register(dir); | |
return FileVisitResult.CONTINUE; | |
} | |
}); | |
} | |
/** | |
* Creates a WatchService and registers the given directory | |
*/ | |
WatchDir(Path dir, boolean recursive) throws IOException { | |
this.watcher = FileSystems.getDefault().newWatchService(); | |
this.keys = new HashMap<WatchKey,Path>(); | |
this.recursive = recursive; | |
if (recursive) { | |
System.out.format("Scanning %s ...\n", dir); | |
registerAll(dir); | |
System.out.println("Done."); | |
} else { | |
register(dir); | |
} | |
// enable trace after initial registration | |
this.trace = true; | |
} | |
/** | |
* Process all events for keys queued to the watcher | |
*/ | |
void processEvents() { | |
for (;;) { | |
// wait for key to be signalled | |
WatchKey key; | |
try { | |
key = watcher.take(); | |
} catch (InterruptedException x) { | |
return; | |
} | |
Path dir = keys.get(key); | |
if (dir == null) { | |
System.err.println("WatchKey not recognized!!"); | |
continue; | |
} | |
for (WatchEvent<?> event: key.pollEvents()) { | |
WatchEvent.Kind kind = event.kind(); | |
// TBD - provide example of how OVERFLOW event is handled | |
if (kind == OVERFLOW) { | |
continue; | |
} | |
// Context for directory entry event is the file name of entry | |
WatchEvent<Path> ev = cast(event); | |
Path name = ev.context(); | |
Path child = dir.resolve(name); | |
// print out event | |
System.out.format("%s: %s\n", event.kind().name(), child); | |
// if directory is created, and watching recursively, then | |
// register it and its sub-directories | |
if (recursive && (kind == ENTRY_CREATE)) { | |
try { | |
if (Files.isDirectory(child, NOFOLLOW_LINKS)) { | |
registerAll(child); | |
} | |
} catch (IOException x) { | |
// ignore to keep sample readbale | |
} | |
} | |
} | |
// reset key and remove from set if directory no longer accessible | |
boolean valid = key.reset(); | |
if (!valid) { | |
keys.remove(key); | |
// all directories are inaccessible | |
if (keys.isEmpty()) { | |
break; | |
} | |
} | |
} | |
} | |
static void usage() { | |
System.err.println("usage: java WatchDir [-r] dir"); | |
System.exit(-1); | |
} | |
public static void main(String[] args) throws IOException { | |
// parse arguments | |
if (args.length == 0 || args.length > 2) | |
usage(); | |
boolean recursive = false; | |
int dirArg = 0; | |
if (args[0].equals("-r")) { | |
if (args.length < 2) | |
usage(); | |
recursive = true; | |
dirArg++; | |
} | |
// register directory and process its events | |
Path dir = Paths.get(args[dirArg]); | |
new WatchDir(dir, recursive).processEvents(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://dzone.com/articles/listening-to-fileevents-with-java-nio
http://www.java2s.com/example/java/file-path-io/monitor-a-specified-directory-for-new-files-arrived.html
https://docs.oracle.com/javase/tutorial/essential/io/notification.html