Win a copy of Cross-Platform Desktop Applications: Using Node, Electron, and NW.js this week in the JavaScript forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Getting java.io.IOException: Stream closed when reading from keyboard a 2nd time - JDK 7  RSS feed

 
Gary Fletcher
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
JDK 7 (1.7)
Windows 7 - not too sure if this is releveant.

Hi all

I am pretty new to all this Java, coming from a C/C++ background, and am having issues when reading from the Keyboard/Console.

I've tried using java.util.scanner as well as the below code, but get the same issue. I would prefer using the java.io.BufferedReader class as I really need to get used to the java.io package, before moving on to java.nio.

The test harness below tries multiple reads from the console (windows). Everything is fine on the 1st read, but on the 2nd hit I get a java.io.IOException: Stream closed IOException generated. I am using try-with resourse management and am wondering if when the try completes the system.in stream is closed instead of my refgerence to it (in).

Any explanations and possible solutions would be greatly appreciated.

main():


KBInputProcessor:
 
Campbell Ritchie
Sheriff
Posts: 55348
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcom eto the Ranch

I haven't read your code, because I think the thread title tells it all.
Have you closed System.in, or a reader/scanner/etc pointing to it? Never close such a scanner/reader, because you close System.in and can never open it again. Have you got two readers trying to read System,in simultaneously? You may be unable to get two readers to point to it, but I am not sure on that point.

I would recommend Scanner for reading from the keyboard. I think most people (and many books) don't use it right. If you give a Scanner the wrong input, you suffer an Exception. If you look here, you are supposed to find that particular Exception is only ever used by Scanner, only that page doesn't seem to be working today
A long time ago, Rob Spoor pointed out to me that you can avoid that Exception completely like thisNow, I suggest you are going to use that sort of code hundreds of times, so you don't want to write it again. So it belongs in a utility class. If you search my posts for utility class and hasNextInt, you will probably find a utility class, or more precisely enough parts of a utility class that you can create your own. So, whenever you want an int fro mthe keyboard, you call KeyboardInputs.getInt() (or whatever else you called it) and Bob's your uncle.
 
Campbell Ritchie
Sheriff
Posts: 55348
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am not convinced about the processInput method. You appear to reject the input, and the if will cause an invalid return value. Don't return anything invalid. Either return something valid or throw an Exception. You would get a valid input if you used a loop in the processInput method rather than selection.
The reason you get multiple Exceptions is that you are catching the Exception in the wrong place. What happens is that you fail to read, but catch the Exception too close to the failure. So you go back to the main method and go through the loop. Meanwhile, while you are not watching, the InputStream “System.in”, which implements AutoCloseable has gone out of scope. Although you did not write in.close() anywhere, you are using try‑with‑resources, which closes the Stream at the end of the try statement.
It is worth learning buffered readers, but once you learn Scanner you will probably prefer it.
If you simply threw the Exception from the processInput method, catching it in main(), and if you had the loop in processInput, I think you would not suffer this problem. But there is still a risk of multiple Scanners pointing to #system.in interfering with one another.

I am going to duplicate this thread in another forum because it strikes me as an interesting question which merits the most exposure to potential answers, and the most opportunity for people to disagree with me .
 
Gary Fletcher
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Richie

I have made the input stream variable a class level variable and changed the try‑with‑resources to a regular try, testing the in variable for null in processInput to determine if a new BufferedReader is required. This has now done the trick with the IOException error on Stream closing.

The use of an Exception is excellent instead of returning an empty string on invalid response, and I also like the idea of looping within the processInput() method until a valid response is recieved.

Thanks for these suggestions. Back to the design drawing board.
 
Gary Fletcher
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I was also wondering whether to make the in variable static , at class level?

Could this cause major issues if threading, or could I just declare the appropriate methods as synchronized tro overcome any issues with a static inputstream resource?
 
Campbell Ritchie
Sheriff
Posts: 55348
157
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You only have one instance of System.in. You can hardly use several instances of it. So, if you have one Scanner/Reader pointing to System.in, that will do. If you only have one of anything, it might as well be a static field.

But I still think it ought to be a static field in a utility class. Those of us who remember Java1.4 also remember writing classes for keyboard input, which should, similarly, be utility classes.
You probably will have race conditions in a threaded environment. I don't know whether synchronising each method would be sufficient.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!