如何判断 BufferedReader 流是否已关闭

15

我有两个Java线程。

第一个线程正在关闭一个bufferedreader (br.close())

当第二个线程在同一个reader上进行读取时,会出现IOException(流已关闭)

即使我使用br.ready()也会出现此异常。

是否有一种方法可以知道该流是否已关闭?


4
只是出于好奇,为什么多个线程要使用同一个BufferedReader? - Adam Paynter
很长的故事,先生。我正在尝试让一些旧代码正常工作... - Guru
请注意,使用读取器时一定要非常小心地检查使用作为监视器的确切对象。 - Tom Hawtin - tackline
6个回答

8
方法ready()会在关闭时抛出异常,但即使添加了一个检查已关闭的方法,只要在调用之间释放锁(对于BufferedReader而言是这样),读取时读者可能已经关闭。
我看到三种选择:
  1. 使用try/catch块包装您的读取调用以处理关闭情况。
  2. 创建一个BufferedReader子类,扩展close(),将其设置为自己的变量, 可以用来检查读取器是否已关闭。如果您想让其除了抛出IOException之外执行其他操作,则需要重写很多方法。
  3. 添加自己的锁,并使用它来关闭读取器(一个线程)并检查缓冲区是否准备好并从中读取。可以直接设置变量进行检查,或者将ready()read()调用分组到同一同步块中。

1

我认为没有任何直接调用的方法可以告诉你一个流是否已关闭。

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


对我来说也是这样。我在JDK中检查了BufferedReader.java文件。有一个名为ensureOpen的私有方法,用于检查流是否关闭并抛出Stream Closed异常。它检查内部Reader(用于初始化BufferedReader的那个)是否为空。这在外部是不可访问的。 - Guru

1

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

没有办法避免这种情况。相反,您应该预期读取操作会抛出异常,并准备妥善处理它。


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

2
那是Kathy在2中说的 :) - Alexandru Luchian

0

确实,查看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");
 }

2
小心 - 这可能会很慢,如果类的内部发生变化可能会出错。我建议使用自己的“标志”来保护缓冲区。 - Robert Munteanu
自从Java 1.5以来,反射的速度不再像以前那样慢了。 - Alexandru Luchian

0

如果只有从BufferedReader读取并关闭它的线程,我会创建同步块并在关闭Reader时设置一些标志。因此,在每个线程中,您应该:

  1. 打开同步块。
  2. 检查流是否已关闭(检查标志)。
  3. 从流中读取。
  4. 关闭流。
  5. 设置标志。
  6. 结束同步块。

只需小心并避免在同步块中出现任何可能挂起的情况。基本上,只需放入必要的内容,仅读取数据,稍后再处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接