getinputstream example ejemplo java process inputstream

example - No se puede leer InputStream desde Java Process(Runtime.getRuntime(). Exec() o ProcessBuilder)



getinputstream java ejemplo (6)

Después de luchar durante días, y probando muchas opciones encontré una solución . Trabajando en Ubuntu 14.04 x64, con jdk 8 u 25. Esta publicación de revisión de código me dio una pista.

El truco es usar InputStream#available() antes de leer cualquier cosa con el BufferedReader . Personalmente tengo dos hilos, uno para stdout y el otro para stderr. Aquí hay un fragmento de ejecución simple que extrapolaré de mi programa. Si no quieres leer todo, simplemente salta a 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; } }

Estoy intentando iniciar un proceso externo con Java y no puedo leer nada de su InputStream.

Si estoy iniciando un proceso con comandos como "ls", "ps" o "kill", todo funciona bien. Puedo iniciar el proceso y obtener información en InputStream o en ErrorStream del proceso.

Si trato de usar un comando como "ftp" o "telnet" tanto InputStream como ErrorStream están bloqueando mi programa cuando intento leer. No se pasa información a través de estos flujos en ningún momento.

¿Alguien puede explicar el comportamiento? ¿No es posible con estos comandos o tengo un problema con mi implementación?

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()); }


Me doy cuenta de que esta pregunta es vieja, pero acabo de experimentar el mismo problema. Para arreglar esto utilicé este código.

List<String> 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();

Parece que el proceso espera que usted también lea la secuencia de Error. La mejor solución para esto es combinar la entrada y el flujo de errores juntos.

Actualizar

No vi que intentaste leer desde la secuencia de errores también. Puede ser que necesites combinarlos manualmente con redirectErrorStream(true)


Necesitas hacer este trabajo en un hilo. Por ejemplo para registrar la salida estándar:

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(); } } }

Entonces necesitas un segundo hilo para el manejo de entrada. Y es posible que desee tratar con stderr al igual que stdout.


Tuve el mismo problema con ftp, hasta que noté que ftp detecta si se llama desde un terminal o no.

Cuando no se llama a ftp desde un terminal, suspende cualquier salida a la salida estándar, a menos que se proporcione la opción verbosa (-v).

La razón del bloqueo de las secuencias es que no se les escribe nada.


Tuve este problema con un programa en C que imprimía a la salida estándar ...

La solución redirectErrorStream(true) con un fflush(stdout) en el código C hizo el truco para mí.


Tuve exactamente el mismo problema. Desafortunadamente

processBuilder.redirectErrorStream(true);

no funcionó para mí; Aunque me dio una idea de lo que está mal. Intente usar la siguiente línea de código para mostrar los contenidos de stderr:

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

Me ayudó a descubrir qué estaba mal con mis comandos de terminal que se ejecutan a través de cada hilo.