При вызове Runtime.getRuntime (). Exec () в цикле, как я могу получить каждый вызов для создания вывода вместо только первого? - PullRequest
0 голосов
/ 30 марта 2012

Я пишу процесс, который будет работать непрерывно, получая сообщения в очереди, которые заставляют его вызывать исполняемый файл и обрабатывать его вывод.Я использую Runtime.getRuntime (). Exec (), чтобы вызвать его, но я получаю вывод только в первый раз.Чтобы легче показать проблему, я поставил ее в цикле.Я использую 'seq 1 5' в качестве standin для исполняемого файла, который будет печатать числа от 1 до 5 каждый в отдельной строке.(Я запускал его как на Mac 10.7, так и на Fedora 14.)

    public static void main(String args[]) {
    for (int i = 0; i < 4; i++) {
        try {
            Process process = Runtime.getRuntime().exec("seq 1 5");
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while (reader.ready() || errReader.ready()) {
                if (reader.ready()) {
                    System.out.println("Process output: " + reader.readLine());
                }
                if (errReader.ready()) {
                    System.err.println("Process error: " + errReader.readLine());
                }
            }
            reader.close();
            errReader.close();
            int result = process.waitFor();
            if (result != 0) {
                System.err.println("Process returned with result " + 0);
            }
            System.out.println("Finished process for iteration " + i);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Вот результат - вы можете увидеть ожидаемый результат процесса только в первом цикле:

Process output: 1
Process output: 2
Process output: 3
Process output: 4
Process output: 5
Finished process for iteration 0
Finished process for iteration 1
Finished process for iteration 2
Finished process for iteration 3

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

Ответы [ 2 ]

1 голос
/ 30 марта 2012
import java.io.*;
public class TP {
    public static void main(String... argv) {
        ProcessBuilder pb = new ProcessBuilder(argv);
        for (int i = 0; i < 4; i++) {
            try {
                Process process = pb.start();
                int result = process.waitFor();
                BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                BufferedReader errReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                while (reader.ready() || errReader.ready()) {
                    if (reader.ready()) {
                        System.out.println("Process output: " + reader.readLine());
                    }
                    if (errReader.ready()) {
                        System.err.println("Process error: " + errReader.readLine());
                    }
                }
                reader.close();
                errReader.close();
                if (result != 0) {
                    System.err.println("Process returned with result " + result);
                }
                System.out.println("Finished process for iteration " + i);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
0 голосов
/ 30 марта 2012

вместо использования BufferedReader, который выполняется в текущем потоке, вы можете использовать потоковое считывающее устройство, например DataFetcher (http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/DataFetcher.java?view=log)

С DataFetcher вы можете добавить FetcherListener, чтобы получать уведомления при поступлении новых данных

...