简体   繁体   English

如果使用输入流从PIPE输入结束,如何使(Java)程序自动结束

[英]How to make (Java) program end automatically if input from PIPE is over using InputStream

This question could be better rephrased as: How do you detect EOF in InputStream without blocking 可以将问题改写为:如何在InputStream中检测EOF而不会阻塞

I have a java program that is able to take input from System.in directly (without using a Scanner), I can also pipe input into the java program directly just like any program. 我有一个Java程序,可以直接从System.in中获取输入(无需使用扫描仪),我也可以像其他程序一样直接将输入通过管道传递到Java程序中。 However, when I pipe input into the program, the program keeps running. 但是,当我通过管道将输入输入程序时,该程序将继续运行。 The idea is to stop the program if input was piped into it, but keep it running if we are waiting for user input. 这个想法是在输入管道后停止程序,但在等待用户输入时保持程序运行。

My question is how do I use an InputStream to detect when the pipe is over (and end the program)? 我的问题是如何使用InputStream检测管道何时结束(并结束程序)? If I was using a Scanner I understand that I would be able to use Scanner#hasNext() to detect if I can read more however, I would like to do this just with an InputStream if possible. 如果我使用的是Scanner,我知道我可以使用Scanner#hasNext()来检测是否可以读取更多内容,如果可能的话,我想仅使用InputStream进行此操作。

My code currently looks something similar to this: 我的代码当前看起来与此类似:

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
}

I am open to simpler solutions. 我愿意接受更简单的解决方案。 The reason I am not using a Scanner object is because I need to read individual chars at a time, not just lines at a time. 我不使用Scanner对象的原因是因为我需要一次读取单个字符,而不仅仅是一次读取行。 The purpose of this program isn't only input from the user, most of the time the input isn't even from System.in, I just included System.in in the above example because it will sometimes be System.in 该程序的目的不仅是来自用户的输入,大多数时候甚至都不是来自System.in的输入,在上面的示例中我只是包含了System.in,因为有时它是System.in

EDIT: For whatever reason, I've dedicated about 2 hours of my life searching the internet for a simple solution for this. 编辑:无论出于何种原因,我一生都花了大约2个小时在互联网上寻找一个简单的解决方案。 I've tried just using an InputStream, and even converted my code to use a ReadableByteChannel (created using Channels.newChannel()) to see if that would work. 我已经尝试过仅使用InputStream,甚至将我的代码转换为使用ReadableByteChannel(使用Channels.newChannel()创建)来查看是否可行。 Every implementation I could find for something that wraps an InputStream is blocking. 对于包装InputStream的东西,我可以找到的每个实现都在阻塞。 I guess the only way to fix this is to use another thread. 我猜想解决此问题的唯一方法是使用另一个线程。 Good luck future viewers. 祝以后的观众好运。

You don't really need in.available() . 您实际上不需要in.available() When the pipe is depleted, your variable len will be -1 and the internal while loop will end. 当管道耗尽时,您的变量len将为-1 ,内部while循环将结束。 You can just break the external while loop depending on your need. 您可以根据需要break外部while循环。

Sitting in a while loop and calling in.available is not efficient. 坐在while循环中并调用in.available效率不高。 It will use a lot of CPU. 它将占用大量CPU。

If you call in.read() and it returns -1 then it means there is no more input to read. 如果调用in.read()并返回-1,则意味着没有更多输入可读取。 So you should do this but of course then it blocks. 因此,您应该执行此操作,但是当然会阻塞。

If you need to do something else while this is going on then use a different Thread for the other code. 如果在进行此操作时需要执行其他操作,请对其他代码使用其他线程。 Make sure to set that other thread as a daemon thread so it does not keep the program running when this main thread's method finishes. 确保将另一个线程设置为守护程序线程,以便当该主线程的方法完成时,它不会使程序保持运行。

Simply remember whether read() returned -1 , ie increase the scope of len . 简单地记住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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM