Unable to read from newly locked file
Asked Answered
I

3

0

So I try to locked the file to read it, but I got IOException, any idea why?

public static void main(String[] args){
    File file = new File("C:\\dev\\harry\\data.txt");

    FileReader fileReader = null;
    BufferedReader bufferedReader = null;
    FileChannel channel = null;
    FileLock lock = null;
    try{
        channel  = new RandomAccessFile(file, "rw").getChannel();
        lock = channel.lock();
        fileReader = new FileReader(file);
        bufferedReader = new BufferedReader(fileReader);
        String data;
        while((data = bufferedReader.readLine()) != null){
            System.out.println(data);
        }
    }catch(IOException e){
        e.printStackTrace();
    }finally{
        try {
            lock.release();
            channel.close();
            if(bufferedReader != null) bufferedReader.close();
            if(fileReader != null) fileReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

and I got this error IOException: The process cannot access the file because another process has locked a portion of the file

Insuperable answered 14/6, 2011 at 14:27 Comment(7)
Don't you have to use the NIO methods to access the file once you've locked it?Jade
@Jeff: I am not sure. This is my first time, writing code locking file.Insuperable
is the file open anywhere else (maybe in an editor somewhere that locks everything that it has open (like M$ tools do))Shermanshermie
@Jeff, damn it. How could you pick up something that I've not thought of. I neeeeed sleeeeep.Factual
@Harry, he's right I believe. The FileChannel class has read and write methods. Using those would prevent the problem. Using FileReader would end up using a different file descriptor.Factual
@Vineet: I see, this might be a stupid question, but I need to use readLine here, the FileChannel only have read, is it at all possible if you can show me how to use FileChannel to read line?Insuperable
@Harry, you'll need to read from the ByteBuffer, and there won't be an equivalent method to readLine(). You'll need to read the bytes, or read the primitives.Factual
J
3

Might as well add this as an answer instead of a comment.

If you use the FileLock API you need to use the corresponding NIO file apis.

Jade answered 14/6, 2011 at 14:35 Comment(0)
F
1

Reproducing my answer from here (in case it gets deleted), and adding Jeff Foster's feedback:

Considering that an instance of the OverlappingFileLockException exception is thrown, it appears that another thread in the same process is attempting to lock on the same file. This is not a conflict between A and B, but rather a conflict within B, if one goes by the API documentation on the lock() method and when the condition under which it throws OverlappingFileLockException:

If a lock that overlaps the requested region is already held by this Java virtual machine, or if another thread is already blocked in this method and is attempting to lock an overlapping region of the same file

The only solution to prevent this, is to have any other thread in B prevented from acquiring a lock on the same file, or the same overlapping region in the file.

The IOException being thrown has a bit more interesting message. It probably confirms the above theory, but without looking at the entire source code, I cannot confirm anything. The lock method is expected to block until the exclusive lock is acquired. If it was acquired, then there ought to be no problem in reading from the file. Except for one condition. If the file has already been opened (and locked) by the same JVM in a different thread, using a File object (or in other words, a second/different file descriptor), then the attempted read on the first file descriptor will fail even if the lock was acquired (after all, the lock does not lock out other threads).

An improved design, would be to have a single thread in each process that acquires an exclusive lock on the file (while using a single File object, or a single file descriptor) for only a certain amount of time, perform the required activity in the file, and then release the lock.

As Jeff has pointed out, using the NIO APIs would probably result in resolution of the problem. This is entirely due to the possibility of the FileReader API opening a new file descriptor, which is different from the one that the lock is obtained on.

Factual answered 14/6, 2011 at 14:39 Comment(0)
A
0

Maybe what you want is something more like:

FileInputStream fis = new FileInputStream(file);
channel = fis.getChannel();
channel.lock();
bufferedReader = new BufferedReader(new InputStreamReader(fis));
Antisana answered 14/6, 2011 at 14:35 Comment(2)
I am not sure if this code work. This would be what I want, but I got an exception when I do FileLock lock = channel.lock(). Can you check your code?Insuperable
This definitely does not work. You can only obtain locks on write channels. Otherwise you get a NonWriteableChannelException.Proximal

© 2022 - 2024 — McMap. All rights reserved.