Java - locking a file for exclusive access
-
05-05-2021 - |
Pergunta
My problem is this: I'm using a WatchService
to get notified about new files in a specific folder, now if a file gets moved/copied or created in said folder an event gets triggered and the name of the new file gets returned. The problem now is, if I try to access the file and it is not fully there yet (e.g. the copy is still in progress) an exception gets raised. What i tried was to do something like this:
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
FileChannel fc = raf.getChannel();
FileLock lck = fc.lock();
But even if a lock gets acquired, sometimes still an Exception gets raised if I try to write to the file because another process has still an open handle to it.
Now, how can a file in Java be locked for truly exclusive access?
Solução
For me, the statement
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
returns a FileNotFoundException if I cannot acquire a lock on the file. I catch the filenotfound exception and treat it...
public static boolean isFileLocked(String filename) {
boolean isLocked=false;
RandomAccessFile fos=null;
try {
File file = new File(filename);
if(file.exists()) {
fos=new RandomAccessFile(file,"rw");
}
} catch (FileNotFoundException e) {
isLocked=true;
}catch (Exception e) {
// handle exception
}finally {
try {
if(fos!=null) {
fos.close();
}
}catch(Exception e) {
//handle exception
}
}
return isLocked;
}
you could run this in a loop and wait until you get a lock on the file. Wouldn't the line
FileChannel fc = raf.getChannel();
never reach if the file is locked? You will get a FileNotFoundException thrown..
Outras dicas
its better not to use classes in thejava.io package, instead use the java.nio package . The latter has a FileLock class that you can use for a lock to a FileChannel.
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();
/*
use channel.lock OR channel.tryLock();
*/
// 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 - if it is not null!
if( lock != null ) {
lock.release();
}
// Close the file
channel.close();
} catch (Exception e) {
}