I am watching a directory using java.nio.file.WatchService
;
and every time a file is created I call processFile()
passing it the File handle.
Here is the code for the watcher:
boolean poll = true;
System.out.println("Watching Directory: "+path.toString()+"...");
while (poll) {
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
WatchEvent<Path> ev = cast(event);
Path dir = (Path)key.watchable();
Path fullPath = dir.resolve(ev.context());
File file = new File(fullPath.toString());
System.out.println("Event kind:" + event.kind()
+ ". File affected: " + event.context()
+ ". Full path" + fullPath);
if(event.kind() == ENTRY_CREATE) fileProcessor.processFile(file);
}
poll = key.reset();
}
Here is the processFile() code:
public void processFile(File file) {
String threadName = "Thread-" + file.getName();
Thread t = ProcessorUtil.getThreadByName(threadName);
if (t == null || !t.isAlive()) {
new Thread(() -> {
try {
Thread.sleep(1000); //HACKY WAY of WAITING
InputStream in = new FileInputStream(file);
someProcess(in);
} catch (Exception e) {
_log.error("Exception: ",e);
}
}, threadName).start();
} else {
System.out.println("File "+file.getName()+" currently being processes");
}
As you can see, I'm waiting for the system to write the file before I can access the FileInputStream
. This doesn't seem right to me, and I wonder if there is a better way of doing this than calling Thread.sleep()
.
The watchservice can send you many events together and might even give CREATE then MODIFY events for same file, or DELETE, CREATE, MODIFY all in same list of events for files being written elsewhere (eg text editor re-writes).
The easiest way to protect from mid-process writes and reports to wait until the watch service pauses. Your logic needs to
ws.take()
for first query, and thenws.poll(1)
if you've already received events:This is snippet from a test program which collates all events and acts on them when no watch results are returned by the last
poll(1)
.If you're only catching CREATE events the
store()
is easy, this version collates multiple kinds to latest sensible type:This cuts down the chance that your event handler for CREATE will clash with the writing operation or miss the end of the file.