This question already has an answer here:
-
How to test if a file is “complete” (completely written) with Java
8 answers
Currently I'm working on the project that does processing files from source directory in one of it's routines. There's a Java process that's looking for specified directory and tries to read and process files if they exist. Files are quit large and updates by other thirdparty process. The question is how can I check if the file is completely written? I'm trying to use file.length()
but looks like even if writing process hasn't been completed it returns actual size. I have a feeling that solution should be platform dependent. Any help would be appreciated.
UPDATE:
This question is not really different from the duplicate but it has an answer with working code snippet that is highly rated.
Does the producer process close the file when its finished writing? If so, trying to open the file in the consumer process with an exclusive lock will fail if the producer process is still producing.
I got the solution working:
private boolean isCompletelyWritten(File file) {
RandomAccessFile stream = null;
try {
stream = new RandomAccessFile(file, "rw");
return true;
} catch (Exception e) {
log.info("Skipping file " + file.getName() + " for this iteration due it's not completely written");
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
log.error("Exception during closing file " + file.getName());
}
}
}
return false;
}
Thanks to @cklab and @Will and all others who suggested to look in "exclusive lock" way. I just posted code here to make other interested in people use it. I believe the solution with renaming suggested by @tigran also works but pure Java solution is preferable for me.
P.S. Initially I used FileOutputStream
instead of RandomAccessFile
but it locks file being written.
One simple solution I've used in the past for this scenario with Windows is to use boolean File.renameTo(File)
and attempt to move the original file to a separate staging folder:
boolean success = potentiallyIncompleteFile.renameTo(stagingAreaFile);
If success
is false
, then the potentiallyIncompleteFile
is still being written to.
I don't think there is a general solution for that. Looking for a file size is wrong as some applications can set file size prior any write call. One of the possibility is to use locking. This will require that writer accrue a write lock ( or exclusive lock ). If you can't modify writer, then you may use tools provided by OS, like fuser on Linux to see is there a process which still accesses the file.
If you plan to use this code on a single platform, you may be able to use NIO's FileLock facility. But read the documentation carefully, and note that on many platforms, the lock is only advisory.
Another approach is to have one process write the file with a name that your process won't recognize, then rename the file to a recognizable name when the write is complete. On most platforms, the rename operation is atomic if the source and destination are the same file system volume.
If you can use Java 1.7, take a look at the NIO tools, specifically java.nio.channels.FileChannel
here is an example of locking the file and reading it.