为什么不能重新打开封闭(标准)流?

时间:2015-11-05 21:38:30

标签: java

System.in是提供用户输入数据的“标准”输入流。关闭后,无法重新打开此流。一个这样的例子是在使用扫描仪读取用户输入的情况下如下:

public class Test {
    public static void main(String[] args) {

        boolean finished;

        do {
            Scanner inputScanner = new Scanner(System.in);
            finished = inputScanner.hasNext("exit");
            boolean validNumber = inputScanner.hasNextDouble();
            if (validNumber) {
                double number = inputScanner.nextDouble();

                System.out.print(number);
            } else if (!finished) {
                System.out.println("Please try again.");
            }
            inputScanner.close();
        } while (!finished);
    }
}

在此示例中,创建了类型Scanner的实例,并用于从用户读取一系列数字(请忽略此代码的其他详细信息,超出此示例的范围,我知道扫描程序应该在循环外创建和关闭)。在从用户输入检索到数字之后,关闭此Scanner的实例(即,输入流)。但是,当从用户请求另一个号码并创建新实例时,无法再次打开输入流。在这个例子中,它创建了一个无限循环。

问题是:为什么不能重新打开封闭的流?

4 个答案:

答案 0 :(得分:27)

  

为什么不能在Java中重新打开一个封闭的流?

这仅仅是Java流所代表的底层操作系统结构的本质。流本质上是一个数据管道。关闭它后,它就不再存在了。您可以在相同的端点之间创建一个新端点,但这会产生一个根本不同的流。我们可以考虑缓冲和流定位等实现注意事项,但这些都是边缘问题。

您还特别询问了标准流。这些是您无法重新创建的一些情况。操作系统为每个进程提供一组标准流。一旦它们关闭,就无法获得等价物。您可以在其位置放置不同的流,但无法将它们连接到原始端点。

答案 1 :(得分:9)

关闭标准输入流时:

  • 如果您的输入是由管道提供的,则会通知管道的另一端。它将结束并停止发送数据。没有办法告诉你你犯了一个错误,它应该再次开始发送;

  • 如果您的输入是由文件提供的,则操作系统会删除对该文件的引用,并完全忘记您正在使用它。您无法重新打开标准输入并继续阅读;

  • 如果您的输入是由控制台提供的,则它适用于管道。控制台会收到通知,将关闭管道末端并停止向您发送数据。

所以没有办法重新打开标准输入。

但是......也没有理由关闭标准输入,所以不要这样做!

一个好的模式是:

  • 打开文件的代码或类负责关闭它。

  • 如果将InputStream传递给另一个从中读取的方法,则该方法将其关闭。把它留给打开它的代码。它就像溪流所有者

  • 同样,如果将OutputStream传递给另一个写入它的方法,该方法应该关闭它。将其留给拥有它的代码。但是如果你把流包装在其他可以缓冲一些数据的类中,那么就会调用.flush()来确保一切都出来!

  • 如果您正在围绕InputStream和OutputStream编写自己的包装类,不要关闭终结器中的委托流。如果在GC期间需要清理流,则应自行处理。

在您的示例代码中,不要关闭该扫描仪。您没有打开标准输入,因此您不需要关闭它。

答案 2 :(得分:3)

因为Streams是无界的。您可以根据需要从流中查看值。然后完成后只需关闭它。 Streams不会保留内存中的所有数据。流被设计为处理相对大量的数据,这些数据不能保存在存储器中。因此,您无法重新打开流,因为您已经对其进行了循环并耗尽了所有数据。因为流不会将这些数据保存在内存中。他们只是迷失了,这就是为什么你不能重新打开它。创建新流比创建现有流更好。

答案 3 :(得分:0)

Java标准库选择了标准化的"接近InputStream。即使您可以合理地感知某些流(例如从输入控制台传入的数据),逻辑上可重新打开,InputStream代表一种通用方法,因为它旨在涵盖所有可能的InputStream ,其中许多人本质上不可重新开放。正如在JohnBollinger的回答中所描述的那样。