【问题标题】:Unable to read from newly locked file无法从新锁定的文件中读取
【发布时间】:2011-06-14 14:27:35
【问题描述】:

所以我尝试锁定文件来读取它,但我得到了 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

【问题讨论】:

  • 锁定文件后是不是就不用NIO的方法来访问了?
  • @Jeff:我不确定。这是我第一次写代码锁定文件。
  • 是在其他任何地方打开的文件(可能在某个编辑器中锁定了它打开的所有内容(就像 M$ 工具一样))
  • @Jeff,该死的。你怎么能捡起我没想到的东西。我要睡觉了。
  • @Harry,我相信他是对的。 FileChannel 类具有读取和写入方法。使用这些可以防止出现问题。使用 FileReader 最终会使用不同的文件描述符。

标签: java filelock


【解决方案1】:

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

如果使用FileLock API,则需要使用对应的NIO文件api。

【讨论】:

    【解决方案2】:

    here (in case it gets deleted) 复制我的回答,并添加 Jeff Foster 的反馈:

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      也许你想要的更像是:

      FileInputStream fis = new FileInputStream(file);
      channel = fis.getChannel();
      channel.lock();
      bufferedReader = new BufferedReader(new InputStreamReader(fis));
      

      【讨论】:

      • 我不确定这段代码是否有效。这将是我想要的,但是当我执行FileLock lock = channel.lock() 时出现异常。你能检查你的代码吗?
      • 这绝对行不通。您只能获取写入通道的锁。否则你会得到一个 NonWriteableChannelException。
      猜你喜欢
      • 1970-01-01
      • 2022-08-02
      • 2017-03-02
      • 2012-06-22
      • 2018-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多