0

所以我尝试锁定文件来读取它,但是我得到了 IOException,知道为什么吗?

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();
        }
    }
}

我得到了这个错误IOException: The process cannot access the file because another process has locked a portion of the file

4

3 回答 3

3

不妨将其添加为答案而不是评论。

如果使用FileLockAPI 需要使用对应的 NIO 文件 apis。

于 2011-06-14T14:35:12.383 回答
1

从这里复制我的答案(以防它被删除),并添加 Jeff Foster 的反馈:

考虑到OverlappingFileLockException抛出异常的实例,似乎同一进程中的另一个线程正在尝试锁定同一文件。这不是 A 和 B 之间的冲突,而是 B 内部的冲突,如果按照 API 文档中关于 lock() 方法的内容以及它抛出 OverlappingFileLockException 的条件:

如果此 Java 虚拟机已持有与请求区域重叠的锁,或者如果另一个线程已在此方法中阻塞并试图锁定同一文件的重叠区域

防止这种情况的唯一解决方案是阻止 B 中的任何其他线程获取对同一文件或文件中相同重叠区域的锁定。

IOException抛出有一个更有趣的信息。它可能证实了上述理论,但没有查看整个源代码,我无法确认任何事情。该lock方法预计会阻塞,直到获得排他锁。如果它被获取,那么从文件中读取应该没有问题。一种情况除外。如果文件已经被不同线程中的同一个 JVM 打开(并锁定),使用 File 对象(或者换句话说,第二个/不同的文件描述符),那么尝试读取第一个文件描述符将失败,即使如果获得了锁(毕竟,锁不会锁定其他线程)。

一种改进的设计是在每个进程中拥有一个线程,该线程仅在一定时间内获取文件的排他锁(同时使用单个 File 对象或单个文件描述符),在文件,然后释放锁。

正如 Jeff 所指出的,使用 NIO API 可能会解决问题。这完全是由于FileReader API 打开一个新的文件描述符的可能性,这与获得锁的那个不同。

于 2011-06-14T14:39:33.413 回答
0

也许你想要的更像是:

FileInputStream fis = new FileInputStream(file);
channel = fis.getChannel();
channel.lock();
bufferedReader = new BufferedReader(new InputStreamReader(fis));
于 2011-06-14T14:35:15.567 回答