Порядок вывода сообщений из внешнего exe в программе JavaJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Порядок вывода сообщений из внешнего exe в программе Java

Сообщение Anonymous »

У меня есть программа на Java, которой необходимо вызвать внешнюю программу, скажем, pythonStuff.exe
Эта внешняя программа написана на 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 и записи в один файл синхронизированными блоками.
Ни один из них не работает. Каждый раз в моей программе на Java я вижу сообщения stderr перед stdout. Почему это происходит, даже когда я вызываю pythonStuff.exe через cmd.exe?
Интересно то, что когда я использовал 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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»