So your Java app is scanning an uploads directory for files that the user will copy in (perhaps via a Windows share). The only snag is that the files can be very large, and you don’t want to start processing a partially uploaded file. What to do?
So, today’s challenge: finding a way to tell if a given File has completed copying to the upload directory or is still in the process of being copied. A colleague pointed me at nio, and we threw together something to get the job done (we already knew that File.exists() and File.canRead(), so your effort may need to be a little more robust than this one, but this will get you started):
private boolean hasFinishedCopying(File file) {
FileInputStream fis = null;
FileLock lock = null;
try {
fis = new FileInputStream(file);
FileChannel fc = fis.getChannel();
lock = fc.tryLock(0L, Long.MAX_VALUE, true);
} catch (IOException ioe) {
return false;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ioe) {
// give up...
}
}
}
return lock != null;
}
The magic you need to be aware of is that third boolean argument to tryLock() on a FileChannel. That says “I want to try to get a shared lock on this file for reading and I under someone else might be writing at the moment”. That’s just my scenario! (And without that shared switch you’ll end up with a NonWritableChannelException).
There’s probably a better way of accomplishing this task, but I thought I would at least blog up one option that we’ve tested to work, so that I can Google this later (since I am sure this is a problem I faced before!).
Happy locking!