Reputation: 599
I'm using this custom class to simulate the system.console
while debugging in eclipse.
What's confusing me is that reader = new BufferedReader(new InputStreamReader(
System.in));
is returning null after the second called of readLine
.
I thought it was because I had closed System.in, but according to oracle
The close method of InputStream does nothing.
So now I'm stumped. Here's the code:
public class CustomConsole {
public String readLine(String format, Object... args) {
if (System.console() != null) {
return System.console().readLine(format, args);
}
BufferedReader reader = null;
String line = null;
try {
System.out.print(String.format(format, args));
reader = new BufferedReader(new InputStreamReader(
System.in));
line = reader.readLine();
} catch (IOException e) {
Logger.fatal(e.getMessage());
System.exit(-1);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
Logger.error("CustomConsole.readLine(): BufferedReader could not be closed");
e.printStackTrace();
}
} else {
Logger.error("CustomConsole.readLine(): BufferedReader is null");
}
}
return line;
}
public String readLine() {
return readLine("", "");
}
public char[] readPassword(String format, Object... args) {
if (System.console() != null) return System.console().readPassword(format, args);
return this.readLine(format, args).toCharArray();
}
}
Upvotes: 2
Views: 1009
Reputation:
InputStream is an abstract class. System.in will give you an object of a subclass of InputStream that may have the close method implemented differently.
How about modifying the class to have a field to hold the BufferedReader you create? Something like this:
public class CustomConsole {
private BufferedReader reader;
public String readLine(String format, Object... args) {
if (System.console() != null) {
return System.console().readLine(format, args);
} else if (reader == null) {
reader = new BufferedReader(new InputStreamReader(
System.in));
}
return reader.readLine();
...
Add the exception handling code as you wish appropriate. You don't have to close the reader.
Upvotes: 0
Reputation: 15523
The close
method of InputStream
does nothing, but InputStream
can be subclassed and this subclass can implement close
to be anything. This is the case with BufferedInputStream
for example which, on my machine, is the type of System.in
.
When you are closing your reader, you are closing all the underlying resources and therefore closing System.in
. Nothing can then be read afterwards.
To solve this, you can simply remove the code that close the reader altogether, and it will work. It may seem odd to recreate a BufferedReader everytime, then just store it as a field of your CustomConsole
and reuse it next time. Anyway you won't need to close it ever, since it is just a wrapper of a wrapper around System.in, which is handled by the system.
Rewriting your class in that spirit would produce something like this:
public class CustomConsole {
private BufferedReader reader;
public String readLine(String format, Object... args) {
if (System.console() != null) {
return System.console().readLine(format, args);
}
if (reader == null) {
reader = new BufferedReader(new InputStreamReader(System.in));
}
try {
return reader.readLine();
} catch (IOException e) {
Logger.fatal(e.getMessage());
System.exit(-1);
return null;
}
}
// ....
Upvotes: 2