I have a cluster of machines, each running a Java app.
These Java apps need to access a unique resource.txt
file concurrently.
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 !
You can use File. delete() and File. rename(File target) for this purpose.
A new folder is created in the path mentioned. The list of files is obtained using the 'listFiles' function. The file of array is iterated over, and if a file is encountered, a new file path is created and the name of the file is obtained and it is split. The files are renamed to .
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);
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With