Эта внешняя программа написана на Python, она создает новые файлы и отправляет некоторые сообщения через stdout и stderr во время обработка. Для меня это черный ящик.
Когда я запускаю pythonStuff.exe непосредственно из командной строки или с помощью PowerShell, я вижу результат:
This is standard output
This is a message from stderr
This is standard output
This is standard output
This is a message from stderr
Это результат, который я ожидал бы считать «нормальным».
Но когда я вызываю pythonStuff.exe из своей Java-программы часть stderr всегда находится вверху, за ней следует часть stdout:
This is a message from stderr
This is a message from stderr
This is standard output
This is standard output
This is standard output
Тот же результат, что и при вызове pythonStuff.exe, например, из GitBash.
Как решить эту проблему?
Я пробовал несколько разных подходов:
- Классы CommanLine и DefaultExecutor + PumpStreamHandler из библиотеки Apache Commons и с ними разные варианты.
- ProcessBuilder и Process:
- особенно processBuilder.redirectErrorStream(true) иprocessBuilder.inheritIO()
- Два дополнительных потока для чтения из stdout и stderr
- Использование cmd.exe в качестве промежуточного уровня в Java:
new ProcessBuilder("cmd.exe", "/c", "pythonStuff.exe", "configForPythonStuff.json") - Дополнительные потоки для чтения из stdout и stderr и записи в один файл синхронизированными блоками.
Интересно то, что когда я использовал PowerShell в своей программе Java в качестве промежуточного уровня без флаг -NoNewWindow, я смог увидеть вывод в новом окне. И вывод был правильным:
This is standard output
This is a message from stderr
This is standard output
This is standard output
This is a message from stderr
Когда использовался флаг -NoNewWindow, вывод снова был неправильным, поэтому поток stderr был перед стандартным выводом.
EDIT: вот упрощенная версия моего кода при подходе нет. 3 и нет. Использовано 4:
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "pythonStuff.exe", "config.json");
Process process = processBuilder.start();
Thread outputThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
log.info(line);
}
} catch (IOException e) {
}
});
outputThread.start();
Thread errorThread = new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String line;
while ((line = reader.readLine()) != null) {
log.error(line);
}
} catch (IOException e) {
}
});
errorThread.start();
process.waitFor();
outputThread.join();
errorThread.join();
Подробнее здесь: https://stackoverflow.com/questions/790 ... va-program
Мобильная версия