tags:

views:

3149

answers:

4

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?

A: 

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.

skaffman
Yeah, there is no guarantee that the underlying OS, or even file system, supports file locks in any reasonable way.
aperkins
+1  A: 

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();
}
ZZ Coder
That's a good idea at first glance, but: I just ran this code modified with three different files: a Word file, an Excel file and a text file opened with UltraEdit. Only the text file causes the OverlappingFileLockException. The first two caused a FileNotFoundException in RandomAccessFile.open(). You'd have to look at getMessage() in order to determine that the cause is that the file is locked, which is bad. Very bad when you consider that the message is localized by the OS (it's in German on my machine).
Robert Petermeier
You can use file.exists() to avoid locking unexisting resource. And it looks like you need only one: lock() or tryLock().
serge_bg
+2  A: 

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
A: 

@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.

Stuart Jones
That really depends on what filesystem you're using. Not all networked filesystems implement full Unix FS semantics (and yes, renaming things is a horrendous mess because of that, even on supposedly sane systems…)
Donal Fellows