Не удалось прочитать InputStream из Java Process (Runtime.getRuntime (). Exec () или ProcessBuilder)

Я пытаюсь запустить процесс извне с Java и не могу читать ничего из его InputStream.

Если я начинаю процесс с такими командами, как «ls», «ps» или «kill», все работает нормально. Я могу запустить процесс и получить информацию либо на InputStream, либо на ErrorStream процесса.

Если я пытаюсь использовать команду «ftp» или «telnet», как InputStream, так и ErrorStream блокируют мою программу при попытке прочитать. Никакая информация не передается через эти streamи в любое время.

Может ли кто-нибудь объяснить поведение? Это просто невозможно с этими командами или у меня проблема с моей реализацией?

String processName = _configuration.getProgramCommand().getCommand(); ProcessBuilder procBuilder = new ProcessBuilder(processName); System.out.println("Starting process "+processName); _proc = Runtime.getRuntime().exec(processName);// procBuilder.start(); if(!procBuilder.redirectErrorStream()) { _errorWorker = new ProcessErrorWorker(_proc); _errorWorker.start(); } String proc_start_answer = _configuration.getNextCommand().getCommand(); System.out.println("Waiting for process answer '"+proc_start_answer+"'"); BufferedReader input = new BufferedReader(new InputStreamReader(_proc.getInputStream())); String answer = ""; try { System.out.println("inputstream ready: "+input.ready()); answer+=input.readLine(); System.out.println("process answer: "+answer); input.close(); } catch(Exception e) { System.out.print(e.getMessage()); } 

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

  List commandAndParameters = ...; File dir = ...; // CWD for process ProcessBuilder builder = new ProcessBuilder(); builder.redirectErrorStream(true); // This is the important part builder.command(commandAndParameters); builder.directory(dir); Process process = builder.start(); InputStream is = process.getInputStream(); 

Похоже, что процесс ожидает, что вы также прочитаете из streamа ошибок. Лучшее решение для этого – объединить stream ввода и ошибки вместе.

Обновить

Я также не видел, чтобы вы попытались также прочитать stream ошибок. Это может быть просто то, что вам нужно объединить их вручную с помощью redirectErrorStream(true)

Вам нужно сделать эту работу в streamе. Например, для регистрации стандартного вывода:

 Process process = Runtime.getRuntime().exec(command); LogStreamReader lsr = new LogStreamReader(process.getInputStream()); Thread thread = new Thread(lsr, "LogStreamReader"); thread.start(); public class LogStreamReader implements Runnable { private BufferedReader reader; public LogStreamReader(InputStream is) { this.reader = new BufferedReader(new InputStreamReader(is)); } public void run() { try { String line = reader.readLine(); while (line != null) { System.out.println(line); line = reader.readLine(); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } } 

Тогда вам понадобится второй stream для обработки ввода. И вы можете иметь дело с stderr так же, как stdout.

У меня была проблема с печатью на C-программе в stdout …

Решение redirectErrorStream(true) с fflush(stdout) в коде C сделало трюк для меня.

После того, как я боролся в течение нескольких дней и пытался найти множество вариантов, я нашел решение . Работа над Ubuntu 14.04 x64, с jdk 8 u 25. Этот пост кодосмотра дал мне подсказку.

Хитрость заключается в использовании InputStream#available() перед чтением чего-либо с BufferedReader . У меня лично есть два streamа: один для stdout и другой для stderr. Вот простой исполняемый fragment, который я экстраполировал из своей программы. Если вы не хотите читать все, просто readLine() к readLine()

 import org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.InputStreamReader; import java.io.InputStream; import java.io.BufferedReader; import java.nio.charset.Charset; public class LogHandler { private BufferedReader bufferedReader; private InputStream inputStream; private Thread thread; private boolean isRunning; public void open (InputStream inputStream) { this.inputStream = inputStream; this.bufferedReader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset())); isRunning = true ; if(thread!=null){ thread = new Thread (()->{ while(isRunning) { String line = null; try { line = readLine(); } catch (IOException e) { isRunning = false; } if(line == null) { try { Thread.sleep(150); } catch (InterruptedException ie) { isRunning=false; Thread.currentThread().interrupt(); } } else { System.out.println(line); } } }); } else throw new IllegalStateException("The logger is already running"); thread.start(); } public void close() throws InterruptedException { if(thread!=null){ thread.interrupt(); thread.join(); thread = null; IOUtils.closeQuietly(inputStream); } else throw new IllegalStateException("The logger is not running"); } private String readLine() throws IOException { if(inputStream.available()>0) { // <--------- THIS IS IT int kar = bufferedReader.read(); if (kar != -1) { StringBuilder buffer = new StringBuilder(30); while (kar != -1 && kar != (int) '\n') { buffer.append((char) kar); kar = bufferedReader.read(); } return buffer.toString(); } } return null; } } 

У меня была такая же проблема с ftp, пока я не заметил, что ftp обнаруживает, вызван ли он с терминала или нет.

Когда ftp не вызывается из терминала, он приостанавливает вывод на stdout, если не указана опция verbose (-v).

Причина блокировки streamов заключается в том, что им ничего не написано.

У меня была точно такая же проблема. К сожалению

 processBuilder.redirectErrorStream(true); 

не работал для меня; это дало мне представление о том, что не так. Попробуйте использовать следующую строку кода для отображения содержимого stderr:

 BufferedReader err= new BufferedReader(new InputStreamReader(process.getErrorStream())); 

Это помогло мне выяснить, что было не так с моими командами терминала, проходящими через каждый stream.

  • Как преобразовать InputStream в виртуальный файл
  • Почему InputStream # read () возвращает int, а не байт?
  • Чтение / преобразование InputStream в строку
  • Как объединить два mp3-файла в один (объединение / объединение)
  • CSS-вход с шириной: 100% выходит за пределы родительской привязки
  • Split java.util.Date за два h: поля inputText, представляющие час и минуту с f: convertDateTime
  • Что означает смывание буфера?
  • Можно ли читать из InputStream с таймаутом?
  • Как преобразовать символ в эквивалентное значение System.Windows.Input.Key Enum?
  • Как проверить, нажал ли пользователь клавишу?
  • Давайте будем гением компьютера.