2012-05-11 2 views
1

У меня проблема с интерактивным процессом на Java. У меня есть потоки для чтения STDOUT и STDERR и поток для обработки ввода для процесса. Но в потоке STDOUT нет данных, пока процесс не завершится. Затем весь вывод печатается сразу.Java exec - вывод интерактивного процесса продолжается до завершения процесса

DBG | Pipe action-STDERR started 
DBG | Pipe action-STDIN started 
DBG | Pipe action-STDOUT started 

STDIN | Try to put some input. 
STDIN | I cannot see any output. 
STDIN | Nevertheless the interaction works. 
STDIN | It works on background. 
STDIN | Let's terminate the process to see the truth. 
STDIN | quit 

STDOUT | Enter some text, please: The text is 'Try to put some input.' 
STDOUT | Enter some text, please: The text is 'I cannot see any output.' 
STDOUT | Enter some text, please: The text is 'Nevertheless the' 
STDOUT | Enter some text, please: The text is 'interaction works.' 
STDOUT | Enter some text, please: The text is 'It works on background.' 
STDOUT | Enter some text, please: The text is 'Let's terminate the process to see the truth.' 
STDOUT | Enter some text, please: The text is 'quit' 
STDOUT | Bye! 
DBG | Trying to kill thread action-STDOUT 
DBG | Trying to kill thread action-STDERR 
DBG | Trying to kill thread action-STDIN 
DBG | Pipe action-STDERR finished 
DBG | Finished 
DBG | Pipe action-STDIN finished 
DBG | Pipe action-STDOUT finished 

Линии, начинающиеся с STDOUT, представляют собой линии, написанные процессом. Строки с префиксом STDIN - это строки, написанные мной. Строки, предваряемые DBG, являются строками, написанными проверенной программой Java в качестве отладочной информации. Попробуем выполнить тот же процесс в системной консоли.

Поведение полностью оправдывает мое ожидание. Меня попросили внести свой вклад. Я делаю это и получаю ответ.

Я удивлен, что нашел несколько сообщений в Интернете, включая Stackoverflow, но без ответа, помеченного как приемлемое решение. (Например, Problem reading InputStream from Java Process.) Кажется, разработчики Java никогда не занимались выполнением интерактивного процесса. Странно, что вывод неинтерактивного процесса (как ping) появляется последовательно, а процесс выполняется. Без каких-либо проблем. Но когда процесс ждет ввода пользователя, выход каким-то образом блокируется.

+0

Каков другой процесс («сервер»), написанный на нем, и не заставляет ли он каждый раз выгружать его стандартную версию? –

+0

Наверное, нет, но этот процесс является черным ящиком на этом уровне. Не имеет значения, удаляет ли он свои выходы или нет, потому что я не могу повлиять на него. Я должен решить проблему внутри кода Java. –

ответ

1

К сожалению, это не ошибка, это особенность. Либо на Linux, либо на Windows-каналы реализованы так. Они забуферированы, чтобы увеличить производительность. Один процесс создает данные, а второй - их. Не требуется никакого взаимодействия, и эта модель работает и в 99% случаев.

Однако консоль - это другой вид приложения. Системная консоль является частью ОС, и она немного отличается от нашей консоли, написанной на Java. Разумеется, системная консоль печатает сразу все данные. Все работает нормально. Тогда тот же самый процесс, выполненный из нашего кода, не печатает подсказки, хотя он будет работать. Что не так? Между консолью системы и процессом нет буфера. Но есть буфер между нашим процессом и нашим Java-кодом, наоборот. И в этом причина.

Процесс не выдает автоматический вывод. Независимо от языка, на котором написан процесс. Процесс, написанный на Java, Perl или C, никогда не выводит подсказки, пока в его код не добавится явный флеш. Если вы можете повлиять на код процесса вы будете взаимодействовать, обновлять код (псевдокод следует):

print 'Give me a number ' 
flush STDOUT 
number = get STDIN 
print 'You wrote ' + number 
flush STDOUT 

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

Совет: Отъезд Apache Commons Exec. Это библиотека, специализирующаяся на выполнении процесса.

Смежные вопросы