views:

1411

answers:

6

I have two threads in Java.

First thread is closing a bufferedreader (br.close())

When the second thread does a read on the same reader I get an IOException (Stream Closed)

I get this exception even if I use br.ready()

Is there a way to know if the stream is already closed?

+1  A: 

I don't think there's any method you can call directly to tell if a stream is closed.

If you really need to have two threads sharing this reader, your best option might be to have the one thread call back to the other thread or set a flag to notify it that the stream has been closed so the other thread knows not to try to read from it.

Eric Petroelje
that seemed like the case to me too. I checked the BufferedReader.java in JDK. There is a ensureOpen private method that checks for stream close and throws the Stream Closed exception. It is checking if the internal Reader (the one used to initialize the BufferedReader) is null. That is not accessible outside.
+1  A: 

If you have already started a read operation, then you will notified with an IOException that a stream is closed. Even if you have called br.ready() before, the exception is happening when your code is blocked at the read method.

There is no way to avoid this. On the contrary, you should expect a read operation to throw an exception and be prepared to handle it appropriately.

kgiannakakis
A: 

Indeed, looking at ensureOpen() it checks if the in object is not null. Since it is private we can't access it from outside. But if you really need it, you can use reflection.

 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");
 }
Alexandru Luchian
This seems to work stand alone. Let me try this on the server..
Careful - this might be probably slow and might break if the internals of the class change. I suggest using your own 'flag' to guard the buffer.
Robert Munteanu
Since Java 1.5 reflection is not as slow as it was before.
Alexandru Luchian
A: 

The method ready() will throw an exception if closed. But even if you added a closed check method, so long as the lock is released between calls (which it is for BufferedReader), the reader might be closed by the time you read it.

I see three options:

  1. Wrap your read call with a try/catch block to handle the closed case.
  2. Create a subclass of BufferedReader that extends close() to set your own variable that can be used to check to see if the reader is closed. This also requires overriding a lot of methods to do whatever the behavior you want with a closed reader if you want it do something beside throw the IOException.
  3. Add a lock of your own and use it to both close the reader (one thread) and check that the buffer is ready and read from it. You can either set a variable directly for the check or just group the ready() and read() calls into the same synchronized block.
Kathy Van Stone
A: 

Another way would be to extend a BufferedReader in your own class, overriding close() method to indicate if it was closed.

Yoni Roit
That's what Kathy said in 2 :)
Alexandru Luchian
A: 

If only things that read from BufferedReader and close it are your threads, I would just make synchronized section and set some flat when closing the Reader. So in each thread you should:

  1. Open synchronized section.
  2. Check if stream isn't closed already (check the flag).
  3. Read from stream.
  4. Close stream.
  5. Set the flag.
  6. End synchronized section.

Just be careful and avoid anything that could hang in synchronized section. Basically put there only what is necessary, only read data, process it later.

amorfis