I need to write a custom batch File renamer. I've got the bulk of it done except I can't figure out how to check if a file is already open. I'm just using the java.io.File package and there is a canWrite() method but that doesn't seem to test if the file is in use by another program. Any ideas on how I can make this work?
I don't think you'll ever get a definitive solution for this, the operating system isn't necessarily going to tell you if the file is open or not.
You might get some mileage out of java.nio.channels.FileLock
, although the javadoc is loaded with caveats.
Your best bet is to set an exclusive lock on the file. If file is open by other processes, you will get an exception. For example,
File file = new File(fileName);
FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
// Get an exclusive lock on the whole file
FileLock lock = channel.lock();
try {
lock = channel.tryLock();
// Ok. You get the lock
} catch (OverlappingFileLockException e) {
// File is open by someone else
} finally {
lock.release();
}
This whole issue is fraught with portability issues and race conditions:
- You could try to use FileLock, but it is not necessarily supported for your OS and/or filesystem.
- It appears that on Windows you may be unable to use FileLock if another application has opened the file in a particular way.
- Even if you did manage to use FileLock or something else, you've still got the problem that something may come in and open the file between you testing the file and doing the rename.
A simpler and (probably) more robust solution is to just try the rename and diagnose any Java exceptions that arise due to opened files.
@Stephen C
Rename would not fail on an open file on most file systems on Unix. Files can be renamed or deleted from a directory and open file handles will still be valid and still be used to read and write to the file.