如果使用 InputStream 来自 PIPE 的输入结束,如何使(Java)程序自动结束

这个问题可以更好地改写为:How do you detect EOF in InputStream without blocking


我有一个能够直接从 System.in 获取输入的 java 程序(不使用扫描器),我也可以像任何程序一样直接将输入输入到 java 程序中。但是,当我将输入输入到程序中时,程序会继续运行。这个想法是如果输入被输入到程序中,则停止程序,但如果我们正在等待用户输入,则保持程序运行。


我的问题是如何使用 InputStream 来检测管道何时结束(并结束程序)?如果我使用的是 Scanner,我知道我可以使用Scanner#hasNext()来检测我是否可以阅读更多内容,但是如果可能的话,我想只使用 InputStream 来做到这一点。


我的代码目前看起来与此类似:


final InputStream in = System.in; // sometimes in won't be System.in

final byte[] buffer = new byte[1024];

while(true){

    int len;

    // the reason I use in.available() is so I only read if in.read() won't block

    while(in.available() > 0 && (len = in.read(buffer)) > -1){

        String s = new String(buffer, 0, len);

        // do something with string

    }

    // sometimes do other stuff not relevant to this question

}

我愿意接受更简单的解决方案。我不使用 Scanner 对象的原因是因为我需要一次读取单个字符,而不仅仅是一次读取行。这个程序的目的不仅仅是来自用户的输入,大多数时候输入甚至不是来自 System.in,我只是在上面的例子中包含了 System.in,因为它有时是 System.in


编辑:无论出于何种原因,我花了大约 2 个小时的时间在互联网上搜索一个简单的解决方案。我试过只使用 InputStream,甚至将我的代码转换为使用 ReadableByteChannel(使用 Channels.newChannel() 创建)来查看是否可行。我能找到的每个包装 InputStream 的实现都是阻塞的。我想解决这个问题的唯一方法是使用另一个线程。祝未来的观众好运。


浮云间
浏览 471回答 3
3回答

哔哔one

你真的不需要in.available()。当管道耗尽时,您的变量len将是-1并且内部 while 循环将结束。您可以break根据需要只使用外部 while 循环。

慕无忌1623718

坐在 while 循环中并调用 in.available 效率不高。它将使用大量的 CPU。如果你调用 in.read() 并且它返回 -1 则意味着没有更多的输入可以读取。所以你应该这样做,但当然它会阻塞。如果您需要在此过程中执行其他操作,请为其他代码使用不同的线程。确保将其他线程设置为守护线程,这样当主线程的方法完成时,它就不会让程序继续运行。

慕仙森

只需记住是否read()返回-1,即增加范围len。final InputStream in = System.in;final byte[] buffer = new byte[1024];for (int len = 0; len != -1; ) {    while (in.available() > 0 && (len = in.read(buffer)) != -1) {        String s = new String(buffer, 0, len);        // do something with string    }    // do other stuff}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java