Как передать ввод в программу Java с помощью bash - PullRequest
19 голосов
/ 20 апреля 2011

Моя Java-программа прослушивает стандартный ввод:

InputStreamReader isReader = new InputStreamReader(System.in);
BufferedReader bufReader = new BufferedReader(isReader);
while(true){
    try {
        String inputStr = null;
        if((inputStr=bufReader.readLine()) != null) {
            ...
        }
        else {
            System.out.println("inputStr is null");
        }
    }
    catch (Exception e) {
        ...
    }
}

Теперь я хочу передать ввод этой программе из bash. Я попробовал следующее:

echo "hi" | java -classpath ../src test.TestProgram

Но это просто печать inputStr is null бесконечное количество раз. Что я делаю не так?

Редактировать 1: обновлен вопрос, включающий больше кода / контекста.


Редактировать 2:

Похоже, у меня та же проблема, что и у этого OP: Ввод данных из командной строки в Java

Как я могу исправить программу, чтобы можно было вводить данные для тестирования, но при нормальной работе программы пользователи также могут вводить данные со стандартного ввода?

Ответы [ 5 ]

6 голосов
/ 20 апреля 2011

Исправлено.После того, как конвейер ввода был завершен, readLine() продолжал возвращать null, поэтому бесконечный цикл продолжал цикл.

Исправление заключается в том, чтобы выйти из бесконечного цикла, когда readLine() возвращает ноль.

4 голосов
/ 29 августа 2012

У вас есть while(true), поэтому вы получите бесконечный цикл.

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

Гораздо лучше сделать так, чтобы ваше утверждение while четко показывало, каково условие выхода:*

String inputStr = "";
while(inputStr != null) {
    inputStr=bufReader.readLine(); 
    if(inputStr != null) {
        ...
    } else {
        System.out.println("inputStr is null");
    }
}
3 голосов
/ 20 апреля 2011

Что я делаю не так?

Я не вижу причин, по которым фрагмент будет вести себя так.Я подозреваю, что проблема в том, что вы не показали нам ...

Например, какую версию echo вы используете?Встроенная оболочка?Стандартный в '/ bin'?Какой-нибудь интересный путь поиска?

Вы можете попробовать несколько простых экспериментов, чтобы определить, находится ли проблема на уровне оболочки / команды или в приложении Java;например,

$ echo hi > tmp
$ cat tmp
$ java -classpath ../src test.TestProgram < tmp
$ cat tmp | java -classpath ../src test.TestProgram

и так далее.

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

(Икак справедливо отмечает @trashgod, вы, возможно, «жирно потрогали» шаг сборки и запустили версию программы, которая больше не соответствует вашему исходному коду.)

1 голос
/ 24 апреля 2014

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

try {
    // Wrap the System.in inside BufferedReader
    // But do not close it in a finally block, as we 
    // did no open System.in; enforcing the rule that
    // he who opens it, closes it; leave the closing to the OS.
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    String line;
    while ((line = in.readLine()) != null) {
        // TODO: Handle input line
    }

    // Null was received, so loop was aborted.

} catch (IOException e) {
    // TODO: Add error handler
}

Если я читаю файл, я слегка его изменяю, чтобы закрыть файл следующим образом

try {
    File file = new File("some_file.txt");

    // Wrap the System.in inside BufferedReader
    // But do not close it in a finally block, as we
    // did no open System.in; enforcing the rule that
    // he who opens it, closes it; leaves the closing to the OS.
    BufferedReader in = new BufferedReader(new FileReader(file));
    try {
        String line;
        while ((line = in.readLine()) != null) {
            // TODO: Handle input line
        }

        // Null was received, so loop was aborted.

    } finally {
        try {
            in.close();
        } catch (IOException e) {
        }
    }

} catch (IOException e) {
    // TODO: Add error handler
}
1 голос
/ 20 апреля 2011

Вы можете рассмотреть возможность использования именованных каналов (fifos), чтобы разрешить как нормальный ввод через управляющий терминал /dev/tty (или /dev/stdin), так и конвейерный ввод через ввод fifo.

См .: Перенаправление ввода приложения (java), но все еще разрешено использование stdin в BASH

...