Java - вывод процесса обработки (построитель)

В моей программе SwingWorker запускается фоновый процесс. Поток ошибок фонового процесса перенаправляется на stdout, а поток stdout записывается (построчно) в JTextArea. Я думал, что потребляю поток stdout с этим

BufferedReader processOut = new BufferedReader(
    new InputStreamReader(p.getInputStream()));

И с этим внутри doInBackground SwingWorker:

String line;
while((line = processOut.readLine()) != null)
    process(line);

На моем компьютере процесс выполняется до конца, и текстовая область периодически обновляется. Однако на других компьютерах процесс зависает в фоновом режиме. Я увеличил размер окна по умолчанию command, поэтому, возможно, я не могу заставить какой-либо процесс зависать на моем компьютере (что, вероятно, очень неправильно, судя по тому, что я читал).

Я попытался перенаправить вывод внутри команды ProcessBuilder с помощью > log.txt (сейчас я использую Windows 7), но я думаю, что это вызывает сбой вызова p.getInputStream().

Как я могу правильно использовать стандартный вывод подпроцесса внутри моего класса SwingWorker, или можно ли передать вывод в файл и по-прежнему получать вывод от print к JTextArea.

Изменить:

Я читал здесь, что входной поток должен быть немедленно прочитан для использования. Я предоставил цикл, который обрабатывает входной поток ниже. Я бы предположил, что канал не получает более 4K данных до того, как он будет прочитан, но я не могу ничего предположить на данный момент.

    while(processIsAlive())
    { 
        if(isCancelled())
        {
            try
            {
                p.destroy();
                p.waitFor();
                return 1;
            }
            catch(Exception e){}
        }

        try
        {
            //Update Text Area

            //get output from process
            while((line = processOut.readLine()) != null)
            {
                //print output to text area
                publish(line);
            }

            sleep(1000);
        }
        catch(Exception e){}
    }

ИЗМЕНИТЬ 2:

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

Все, что я сделал, это перенаправил процесс в файл:

pb.redirectOutput(new File("log.txt"));

И поместите InputStream в этот файл вместо потока процесса stdout.

processOut = new BufferedReader(new FileReader("log.txt"));

person Cullen S    schedule 09.10.2015    source источник


Ответы (2)


При запуске процессов удобно читать stdout и stderr в отдельном потоке каждый, потому что чтение должно выполняться через вызов InputStream.read(), который блокирует поток владельца .

Вы сказали, что ваш фоновый процесс перенаправляет ошибки на стандартный вывод, хорошо. Затем прочтите только стандартный вывод, но всегда делайте это в отдельном потоке, потому что основной поток блокируется при вызове waitFor до завершения процесса. Но процесс заблокируется, если его выходной буфер заполнится и никто его не читает.

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

person Little Santi    schedule 09.10.2015

Мое второе редактирование будет работать на любой машине с Java 7 или новее. Чтение из входного потока блокируется, поэтому его нельзя использовать в графическом интерфейсе, но потоки процесса считываются из него соответствующим образом.

Фактическая проблема с машиной заключалась в том, что по какой-то причине программа не сбрасывалась должным образом, поэтому я добавил fflush (stdout) в исходный код c в проблемной программе, и она отлично сработала.

person Cullen S    schedule 19.10.2015