Как автоматически завершить (Java) программу, если ввод из PIPE закончен с использованием InputStream - PullRequest
0 голосов
/ 14 ноября 2018

Этот вопрос можно перефразировать следующим образом: как вы обнаруживаете EOF в InputStream без блокировки

У меня есть Java-программа, которая может принимать входные данные из System.in напрямую (безиспользуя сканер), я также могу направлять ввод в Java-программу напрямую, как и любая другая программа.Однако, когда я передаю ввод в программу, программа продолжает работать.Идея состоит в том, чтобы остановить программу, если ввод был передан в нее, но продолжать работать, если мы ожидаем ввода пользователя.

Мой вопрос заключается в том, как мне использовать InputStream, чтобы определить, когда канал закончен (иконец программы)?Если бы я использовал сканер, я понимаю, что смог бы использовать 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, блокируется.Я думаю, что единственный способ исправить это - использовать другой поток.Удачи будущим зрителям.

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Сидеть в цикле while и вызывать in.available неэффективно. Он будет использовать много процессора.

Если вы вызываете in.read () и он возвращает -1, то это означает, что больше нет ввода для чтения. Так что вы должны сделать это, но, конечно, тогда он блокируется.

Если вам нужно сделать что-то еще, пока это происходит, используйте другой поток для другого кода. Убедитесь, что этот другой поток задан как поток демона, чтобы он не продолжал выполнение программы после завершения метода этого основного потока.

0 голосов
/ 14 ноября 2018

Просто запомните, вернул ли 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
}
0 голосов
/ 14 ноября 2018

Тебе не нужно in.available(). Когда канал истощится, ваша переменная len будет -1, и внутренний цикл while завершится. Вы можете просто break внешний цикл while в зависимости от ваших потребностей.

...