我正在开发一个名为ConsoleInput的类,它应该简化我正在开发的应用程序的控制台输入。在测试它时,我注意到我似乎无法关闭BufferedReader,并实例化一个新的ConsoleInput类。我可以在不关闭BufferedReader的情况下完成,但它仍然是一个有趣的问题。我想知道为什么我不能关闭它,以及我可以做些什么来改变它。
ConsoleInput类:
package frontend;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.io.*;
public class ConsoleInput {
private BufferedReader buf = null;
private boolean ignoreconfirm = false;
private boolean confirmation = false;
private boolean closed = false;
private String dateformat = "yyyy-MM-dd";
private boolean confirm(String value) throws IOException {
boolean accept = false;
boolean answer = false;
String l = "I";
while (!accept) {
System.out.print(l + "s '" + value + "' correct (Y/N) ?: ");
String line = buf.readLine();
line = line.trim();
line = line.toLowerCase();
if (line.equals("y") || line.equals("yes")) {
accept = true;
answer = true;
} else if (line.equals("n") || line.equals("no")) {
accept = true;
answer = false;
}
if (!accept) System.out.print("Try confirmation again, ");
l.toLowerCase();
}
return answer;
}
public String getString() throws IOException, ExcConsoleInputClosed {
if (closed) throw new ExcConsoleInputClosed();
boolean accept = false;
String line = null;
while (!accept) {
line = buf.readLine();
if (confirmation && !ignoreconfirm) {
accept = confirm(line);
if (!accept) System.out.print("Try input again: ");
} else {
accept = true;
}
}
return line;
}
public Integer getInt() throws IOException, ExcConsoleInputClosed {
boolean accept = false;
boolean parsed = false;
Integer value = null;
String input = null;
while (!parsed) {
if (confirmation) ignoreconfirm = true;
input = getString();
if (confirmation) ignoreconfirm = false;
input.trim();
if (confirmation) accept = confirm(input);
else accept = true;
if (!accept) System.out.print("Try input again: ");
else {
try {
value = new Integer(Integer.parseInt(input));
parsed = true;
} catch (NumberFormatException e) {
System.out.print("Error parsing your input, try again: ");
}
}
}
return value;
}
public Date getDate()
throws IOException, ExcConsoleInputClosed {
boolean accept = false;
boolean parsed = false;
Date value = null;
String input = null;
SimpleDateFormat format = new SimpleDateFormat(dateformat);
while (!parsed) {
if (confirmation) ignoreconfirm = true;
input = getString();
if (confirmation) ignoreconfirm = false;
input.trim();
if (input.equals("help")) {
System.out.println("Enter a date with format " + dateformat + ".");
} else {
if (confirmation) accept = confirm(input);
else accept = true;
if (!accept) System.out.print("Try input again: ");
else {
try {
value = format.parse(input);
parsed = true;
} catch (ParseException e) {
System.out.print("Error parsing your input, try again");
}
}
}
}
return value;
}
public void toggleConfirm() {
confirmation = !confirmation;
}
public boolean confirmation() { return confirmation; }
public void close() throws IOException {
closed = true;
buf.close();
}
public ConsoleInput() {
buf = new BufferedReader(new InputStreamReader(System.in));
}
}
此课程的单元测试:
public class feConsoleInput {
public static void main(String[] args) {
ConsoleInput console = new ConsoleInput();
System.out.println("Fetching input from console.");
for (int c=0; c <= 1; c++) {
try {
System.out.print("Enter a string: ");
String text = console.getString();
System.out.println("You entered: " + text);
System.out.print("Enter a integer: ");
Integer number = console.getInt();
System.out.println("You entered: " + number);
System.out.println("Enter a date...");
Date date = console.getDate();
System.out.println("You entered: " + date.toString());
console.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExcConsoleInputClosed e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("");
console = new ConsoleInput();
console.toggleConfirm();
}
}
}
当它在关闭后第二次运行时,我得到了关闭Stream的IOException。据我所知,ConsoleInput类构造函数应该打开一个新构造函数。
Fetching input from console.
Enter a string: A string of input.
You entered: A string of input.
Enter a integer: 42
You entered: 42
Enter a date...
2012-12-07
You entered: Fri Dec 07 00:00:00 EST 2012
java.io.IOException: Stream closed
Enter a string:
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
at java.io.BufferedInputStream.read(BufferedInputStream.java:325)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:153)
at java.io.BufferedReader.readLine(BufferedReader.java:316)
at java.io.BufferedReader.readLine(BufferedReader.java:379)
at frontend.ConsoleInput.getString(ConsoleInput.java:45)
at test.feConsoleInput.main(feConsoleInput.java:17)
答案 0 :(得分:2)
当您关闭BufferedInputStream
时,它也会关闭基础System.in
流。这无法撤消。
一个常见的解决方案是用CloseShieldInputStream
包裹System.in
以避免在关闭外部阅读器时将其关闭。
public ConsoleInput() {
buf = new BufferedReader(new InputStreamReader(
new CloseShieldInputStream(System.in)));
}
或者,只需在整个程序期间保持ConsoleInput
课程的一个实例。