2

我正在使用这个自定义类来模拟system.consoleeclipse 中的 while 调试。让我感到困惑的是,reader = new BufferedReader(new InputStreamReader( System.in));在第二次调用 of 之后返回 null readLine

我以为是因为我关闭了System.in,但是根据oracle

InputStream 的 close 方法什么也不做。

所以现在我很难过。这是代码:

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();
    }
}
4

2 回答 2

2

close方法InputStream什么也不做,但InputStream可以被子类化,这个子类可以实现close为任何东西。例如BufferedInputStream,在我的机器上,就是System.in.

当您关闭阅读器时,您正在关闭所有底层资源,因此正在关闭System.in. 之后就无法读取任何内容。

要解决这个问题,您可以简单地删除完全关闭阅读器的代码,它会起作用。每次都重新创建一个 BufferedReader 似乎很奇怪,然后将其存储为您的字段CustomConsole并在下次重用它。无论如何,您永远不需要关闭它,因为它只是 System.in 的包装器的包装器,由系统处理。

以这种精神重写你的课程会产生这样的结果:

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;
        }
    }

// ....
于 2013-10-25T16:46:22.087 回答
0

InputStream 是一个抽象类。System.in 将为您提供 InputStream 子类的对象,该对象可能以不同方式实现 close 方法。

如何修改类以拥有一个字段来保存您创建的 BufferedReader?像这样的东西:

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();
        ...

根据需要添加异常处理代码。您不必关闭阅读器。

于 2013-10-25T16:47:56.997 回答