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!