Запись в подпроцесс Java

Я пытаюсь записать на стандартный ввод подпроцесса (оба являются Java-приложениями). Чтение вывода процесса работает нормально, но ввод с использованием PrintStream или PrintWriter не работает. Вот пример программы, которую я написал для проверки странного поведения и запустил ее без аргументов. Затем выполняется та же программа, что и подпроцесс. Подпроцесс просто считывает ввод и отображает его на выходе. Основной процесс принимает стандартный ввод, записывает его на вход подпроцесса и выводит вывод подпроцесса на стандартный вывод.

Проблема в том, что это не работает. nextLine() подпроцесса не совпадает с оператором println() в родительском процессе, поэтому подпроцесс никогда ничего не выводит.

Почему это происходит и как это исправить (желательно в родительском процессе, потому что я не могу изменить дочерний процесс основного проекта).

import java.lang.*;
import java.io.*;
import java.util.Scanner;

public class ProcTest{
    public static Scanner stdin;
    public static String line;
    public static Process sub;

    public static BufferedReader childout;
    public static PrintWriter childin;

    public static void main(String[] args){
            stdin = new Scanner(System.in);
            if(args.length > 0 && args[0].equals("y")){
                    while(true){
                            line = stdin.nextLine();
                            System.out.println(line);
                    }
            }else{
                    try{
                            sub = Runtime.getRuntime().exec("java ProcTest y");
                            childout = new BufferedReader(new InputStreamReader(sub.getInputStream()));
                            childin = new PrintWriter(sub.getOutputStream());
                            while(true){
                                    childin.println(stdin.nextLine());
                                    childin.flush();
                                    while(childout.ready()) System.out.println( childout.readLine() );
                            }
                    }catch(IOException e){
                            e.printStackTrace();
                    }
            }
    }
}

person Brian    schedule 04.11.2012    source источник
comment
Обработка процессов в Java довольно неуклюжая. Можете ли вы просто запустить метод main дочернего процесса напрямую в родительском процессе?   -  person artbristol    schedule 05.11.2012


Ответы (1)


Обычной причиной такого рода вещей является проблема с буферизацией.

В вашем примере программы я вижу одну возможную проблему: в дочернем процессе вы выполняете System.out.println(), но не выполняете сброс после этого. Просмотр документации Javadoc показывает, что PrintStreams может автоматически запускаться, но не указано, настроено ли System.out по умолчанию таким образом, поэтому стоит попробовать.

Обратите внимание, что некоторые платформы решают автоматически запускать стандартный вывод только в том случае, если это терминал (я не знаю, поддерживает ли Java System), что может запутать ситуацию при отладке.

(Я заметил, что вы сказали, что не можете изменить дочерний процесс в реальной ситуации, но если проблема именно в этом, то вы должны изменить дочерний процесс (или, если есть является тестом is-a-terminal, оберните его в псевдотерминал).)

person Kevin Reid    schedule 04.11.2012
comment
Но это одна из самых странных вещей. Я не тестировал этот пример программы, но в основном проекте, над которым я работаю, родительский процесс по-прежнему принимает выходные данные дочернего процесса, но дочерний процесс просто не отвечает, когда родитель пытается с ним связаться. Будет ли проблема с очисткой / невыполнением промывки родительского PrintWriter? - person Brian; 05.11.2012
comment
Родительский код сбрасывается, так что все должно быть в порядке. Никогда не бывает слишком много промывки для корректности (ну, если получатель не делает ошибку, читая только то, что доступно, и неправильно полагает, что это полная строка / пакет / сообщение, что неверно и склонно к сбою под нагрузкой). - person Kevin Reid; 05.11.2012