【问题标题】:How to know if a BufferedReader Stream is closed如何知道 BufferedReader Stream 是否关闭
【发布时间】:2010-11-02 03:28:27
【问题描述】:

我在 Java 中有两个线程。

第一个线程正在关闭缓冲读取器 (br.close())

当第二个线程对同一个阅读器进行读取时,我得到一个IOException (Stream Closed)

即使我使用br.ready(),我也会收到此异常

有没有办法知道流是否已经关闭?

【问题讨论】:

  • 只是出于好奇,为什么多个线程使用同一个BufferedReader?
  • 长篇大论先生......试图让一些遗留代码工作......
  • 请注意,要非常小心地检查哪个对象被用作 Readers 的监视器。

标签: java io bufferedreader


【解决方案1】:

我认为没有任何方法可以直接调用来判断流是否已关闭。

如果你真的需要让两个线程共享这个阅读器,你最好的选择可能是让一个线程回调另一个线程,或者设置一个标志来通知它流已经关闭,这样另一个线程就不知道了尝试从中读取。

【讨论】:

  • 对我来说似乎也是如此。我检查了 JDK 中的 BufferedReader.java。有一个 ensureOpen 私有方法检查流关闭并抛出 Stream Closed 异常。它正在检查内部读取器(用于初始化 BufferedReader 的读取器)是否为空。这是外面无法访问的。
【解决方案2】:

如果您已经开始了读取操作,那么您将通过 IOException 通知流已关闭。即使您之前调用过 br.ready(),当您的代码在 read 方法处被阻塞时也会发生异常。

没有办法避免这种情况。相反,您应该期望读取操作会引发异常并准备好适当地处理它。

【讨论】:

    【解决方案3】:

    确实,查看 ensureOpen() 它会检查 in 对象是否不为空。 由于它是私有的,我们无法从外部访问它。 但是如果你真的需要它,你可以使用反射。

     BufferedReader myBR  = new BufferedReader(new FileReader("c:/somefile.txt"));
     myBR.close();
    
     Class c = myBR.getClass();
     Field in = c.getDeclaredField("in");
     in.setAccessible(true);         
     Object inReader = in.get(myBR);
    
    
     if(inReader == null){
         System.out.println("is closed");
     }
     else{
         System.out.println("is open");
     }
    

    【讨论】:

    • 小心 - 如果类的内部发生变化,这可能会很慢并且可能会中断。我建议使用你自己的“标志”来保护缓冲区。
    • 因为 Java 1.5 的反射不像以前那么慢了。
    【解决方案4】:

    ready() 方法在关闭时会抛出异常。但是即使你添加了一个关闭的检查方法,只要在调用之间释放了锁(它是针对BufferedReader),阅读器可能在你阅读它的时候就被关闭了。

    我看到三个选项:

    1. 使用 try/catch 块包装您的读取调用以处理已关闭的案例。
    2. 创建一个扩展close()BufferedReader 的子类,以设置您自己的变量 可用于检查阅读器是否关闭。这也需要覆盖很多 如果您希望它在抛出IOException 之外执行某些操作,则可以使用封闭式阅读器执行您想要的任何行为的方法。
    3. 添加自己的锁并使用它来关闭阅读器(一个线程)和 检查缓冲区是否已准备好并从中读取。您可以直接为检查设置一个变量,也可以将 ready()read() 调用分组到同一个同步块中。

    【讨论】:

      【解决方案5】:

      另一种方法是在您自己的类中扩展 BufferedReader,覆盖 close() 方法以指示它是否已关闭。

      【讨论】:

      • 这就是凯西在 2 中所说的 :)
      【解决方案6】:

      如果只有从 BufferedReader 读取并关闭它的东西是您的线程,我只会制作同步部分并在关闭 Reader 时设置一些平面。所以在每个线程中你应该:

      1. 打开同步部分。
      2. 检查流是否尚未关闭(检查标志)。
      3. 从流中读取。
      4. 关闭直播。
      5. 设置标志。
      6. 结束同步部分。

      请小心并避免任何可能挂在同步部分的内容。基本上只放必要的,只读取数据,稍后处理。

      【讨论】:

        猜你喜欢
        • 2015-08-31
        • 1970-01-01
        • 2014-03-03
        • 1970-01-01
        • 1970-01-01
        • 2014-12-04
        • 2023-03-24
        相关资源
        最近更新 更多