Reading System.in multiple times in Java causes IOException?
I am playing around trying to create a little command line game to reinforce some of the things I have learnt in Java over the last few months.
I am trying to create a method called readInput() which returns a String which I can call again and again. The first time it works perfectly, the second time however it causes an IO.Exception. If I remove the statement bisr.c开发者_Go百科lose(); it works but was taught to close streams as it is bad practice to leave them open.
Can someone kindly point me in the right direction as I have googled but to no avail.
The method ...
private String readInput()
{
String input = null;
BufferedReader bisr = null;
try
{
bisr = new BufferedReader(new InputStreamReader(System.in));
input = bisr.readLine();
}
catch (Exception e)
{
System.out.println("Error: " + e);
}
finally
{
try
{
bisr.close();
}
catch (Exception e)
{
System.out.println("Error:" + e);
}
return input;
}
}
The problem is that closing the BufferedReader
also automatically closes the InputStreamReader
which implicitly closes System.in
.
And the second time you call that method System.in
is closed, which means you won't be able to read from it.
The "always close it" only really applies to resources that you also opened!
The first time it works perfectly, the second time however it causes an IO.Exception
bisr.close()
will also close the underlying input stream (in this case System.in
). This is why consecutive reads will result in an IOException.
If I remove the statement bisr.close(); it works but was taught to close streams as it is bad practice to leave them open
No problem in keeping System.in
open for the duration of the execution.
If you don't want to create unnecessarily many objects, you can create the BufferedReader once, and pass that around.
For this particular situation, I would probably just go with
private String readInput() {
return new Scanner(System.in).nextLine();
}
For System.in it is better to have a global BufferedReader or Scanner you create once. This is because a BufferedReader and Scanner can read more than one line which it buffers for performance so you could be discarding some lines or parts of lines.
public static void main(String... args) throws InterruptedException {
for(int i=0;i<5;i++) {
System.out.println("\nread "+readLine());
// give me time to write more than one line, no problem from a file.
Thread.sleep(1000);
}
}
public static String readLine() {
// can lose input.
return new Scanner(System.in).nextLine();
}
if I enter the numbers 1,2,3 etc across the keyword quickly.
1
read 1
2
3
4
read 2
5
6
7
read 4
8
9
0
read 7
-
=
read 0
If I use a global Scanner object and do the same thing.
static final Scanner IN = new Scanner(System.in);
public static void main(String... args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
System.out.println("\nread " + readLine());
// give me time to write more than one line, no problem from a file.
Thread.sleep(1000);
}
}
public static String readLine() {
return IN.nextLine();
}
prints
1
read 1
2
3
4
read 2
5
6
read 3
7
8
read 4
9
read 5
0
read 6
read 7
read 8
read 9
read 0
精彩评论