Получить вывод процесса без блокировки

Я хочу получить вывод процесса (Git.exe чтобы быть точным) и преобразовать его в объект String. Ранее иногда мой код был заблокирован. Тогда я понял, что это потому, что процесс ErrorStream имеет некоторый вывод, и я должен вручную захватить это (что меня не интересует). Я изменил свой код на это:

public static String runProcess(String executable, String parameter) {
    try {
        String path = String.format("%s %s", executable, parameter);
        Process pr = Runtime.getRuntime().exec(path);

        // ignore errors
        StringWriter errors = new StringWriter();
        IOUtils.copy(pr.getErrorStream(), errors);

        StringWriter writer = new StringWriter();
        IOUtils.copy(pr.getInputStream(), writer);

        pr.waitFor();
        return writer.toString();
    } catch (Exception e) {
        return null;
    }
}

Теперь он работает в основном нормально, но, опять же, иногда он снова блокируется в этой строке:IOUtils.copy(pr.getErrorStream(), errors);,

Есть ли какой-то способ, которым я мог бы просто получить результат от git.exe не ударяя блок? Благодарю.

2 ответа

Решение

Используя эту прекрасную статью и StreamGobbler Описанный там класс (который я немного модифицировал) решил проблему. Моя реализация StreamGobbler:

class StreamGobbler extends Thread {
    InputStream is;
    String output;

    StreamGobbler(InputStream is) {
        this.is = is;
    }

    public String getOutput() {
        return output;
    }

    public void run() {
        try {
            StringWriter writer = new StringWriter();
            IOUtils.copy(is, writer);
            output = writer.toString();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}

и моя функция:

public static String runProcess(String executable, String parameter) {
    try {
        String path = String.format("%s %s", executable, parameter);
        Process pr = Runtime.getRuntime().exec(path);

        StreamGobbler errorGobbler = new StreamGobbler(pr.getErrorStream());
        StreamGobbler outputGobbler = new StreamGobbler(pr.getInputStream());

        // kick them off concurrently
        errorGobbler.start();
        outputGobbler.start();

        pr.waitFor();
        return outputGobbler.getOutput();
    } catch (Exception e) {
        return null;
    }
}

Используйте ProcessBuilder или Apache commons-exec.

Ваш опубликованный код содержит ошибки, это сложная тема, чтобы получить право.

Другие вопросы по тегам