tags:

views:

6726

answers:

7

I have a java process that opens a file using a FileReader. How can I prevent another (java) process to open this file, or at least make that second process know that the file is already opened? Does this automaticaly makes the second process get an exception if the file is open(which solves my problem) or do i have to explicitly open it in the first process with some sort of flag or argument?

To clarify:

I have a java app that lists a folder and opens each file in the listing for processing it. It processes each file after the other. The processing of each file consists of reading it and doing some calculations based on the contents and it takes about 2 minutes. I also have another java app that does the same thing but instead writes on the file. What i want is to be able to run these apps at the same time so the scenario goes like this. ReadApp lists the folder and finds files A, B, C. It opens file A and starts the reading. WriteApp lists the folder and finds files A,B, C It opens file A sees that is is open (by an exception or whatever way) and goes to file B. ReadApp finishes file A and continues to B. It sees that it is open and continues to C. It is crucial that WriteApp doesnt write while ReadApp is reading the same file or vice versa. They are different processes.

+3  A: 

If you can use Java NIO (JDK 1.4 or greater), then I think you're looking for java.nio.channels.FileChannel.lock()

FileChanel.lock()

KC Baltz
Maybe. Depends on what OP meant by 'process'. "File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine."
Stu Thompson
A: 

use java.nio.channels.FileLock in conjunction with java.nio.channels.FileChannel

Matt
A: 

You an use java.nio.* APIs for locking a file. However that doesn't guarantee locking, It depends on if the underlying OS supports locking or not. As I understand Operating systems like Linux doens't support locking and hence you cannot lock even if you use these APIs

Rejeev Divakaran
Your last sentence is just wrong. Linux DOES support file locking.
bene
+8  A: 

FileChannel.lock is probably what you want.

FileInputStream in = new FileInputStream(file) {
try {
    java.nio.channels.FileLock lock = in.getFileChannel().lock();
    try {
        Reader reader = new InputStreamReader(in, charset);
        ...
    } finally {
        lock.release();
    }
} finally {
    in.close();
}

(Disclaimer: Code not compiled and certainly not tested.)

Note the section entitled "platform dependencies" in the API doc for FileLock.

Tom Hawtin - tackline
More importantly, understand that the lock of for the JVM, and not suitable for locking the file for access by individual threads within a single JVM.
Stu Thompson
i have posted an update. you are right.
Paralife
A: 

Use a RandomAccessFile, get it's channel, then call lock(). The channel provided by input or output streams does not have sufficient privileges to lock properly. Be sure to call unlock() in the finally block (closing the file doesn't necessarily release the lock).

Kevin Day
can you elaborate? I mean, to what extend is the lock by RandomAccess File better or safer than streams one
Paralife
Link to simple example posted below
Touko
Paralife - sorry for the delay - just noticed your question. The locks from streams are going to be read locks (for input streams) and exclusive, full channel write locks (for output streams). My experience has been that the locks from RAF allow for more fine grained control (i.e. you can lock portions of a file).
Kevin Day
+2  A: 

This may not be what you are looking for, but in the interest of coming at a problem from another angle....

Are these two Java processes that might want to access the same file in the same application? Perhaps you can just filter all access to the file through a single, synchronized method (or, even better, using JSR-166)? That way, you can control access to the file, and perhaps even queue access requests.

pkaeding
A: 

Simple example using RandomAccessFile as Kevin Day suggested can be found in the question How to prevent file from being overridden when reading and processing it with Java?

Touko