Q:

How to atomically rename a file in Java, even if the dest file already exists?

I have a cluster of machines, each running a Java app.
These Java apps need to access a unique resource.txt file concurently.
I need to atomically rename a temp.txt file to resource.txt in Java, even if resource.txt already exist.
Deleting resource.txt and renaming temp.txt doesn't work, as it's not atomic (it creates a small timeframe where resource.txt doesn't exist).
And it should be cross-platform...
Thanks !

A:

For Java 1.7+, use java.nio.file.Files.move(Path source, Path target, CopyOption... options) with CopyOptions "REPLACE_EXISTING" and "ATOMIC_MOVE".
See API documentation for more information.
For example:
Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE);

A:

On Linux (and I believe Solaris and other UNIX operating systems), Java's File.renameTo() method will overwrite the destination file if it exists, but this is not the case under Windows. 
To be cross platform, I think you'd have to use file locking on resource.txt and then overwrite the data.

The behavior of the file lock is
  platform-dependent. On some platforms,
  the file lock is advisory, which means
  that unless an application checks for
  a file lock, it will not be prevented
  from accessing the file. On other
  platforms, the file lock is mandatory,
  which means that a file lock prevents
  any application from accessing the
  file.

try {
    // Get a file channel for the file
    File file = new File("filename");
    FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

    // Use the file channel to create a lock on the file.
    // This method blocks until it can retrieve the lock.
    FileLock lock = channel.lock();

    // Try acquiring the lock without blocking. This method returns
    // null or throws an exception if the file is already locked.
    try {
        lock = channel.tryLock();
    } catch (OverlappingFileLockException e) {
        // File is already locked in this thread or virtual machine
    }

    // Release the lock
    lock.release();

    // Close the file
    channel.close();
} catch (Exception e) {
}

Linux, by default, uses voluntary locking, while Windows enforces it. Maybe you could detect the OS, and use renameTo() under UNIX with some locking code for Windows?
There's also a way to turn on mandatory locking under Linux for specific files, but it's kind of obscure. You have to set the mode bits just right.

Linux, following System V (see System
  V Interface Definition (SVID) Version
  3), lets the sgid bit for files
  without group execute permission mark
  the file for mandatory locking

A:

Here is a discussion that relates: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4017593

