example ejemplo java stream processbuilder

java - ejemplo - ¿Cómo redirigir la salida de Process Builder a una cadena?



process java example (8)

Estoy usando el siguiente código para iniciar un generador de procesos. Deseo saber cómo puedo redirigir su salida a una Cadena.

ProcessBuilder pb = new ProcessBuilder(System.getProperty("user.dir")+"/src/generate_list.sh", filename); Process p = pb.start();

Intenté usar ByteArrayOutputStream pero no pareció funcionar.


Después de tratar de manejar diferentes casos (manejando stderr y stdout y no bloqueando ninguno de ellos, finalizo el proceso después del tiempo de espera, escapé correctamente barras, comillas, caracteres especiales, espacios, ....) Me rendí y encontré Apache Commons Exec https://commons.apache.org/proper/commons-exec/tutorial.html que parece estar haciendo todas estas cosas bastante bien.

Recomiendo a todos los que necesiten invocar procesos externos en Java que utilicen la biblioteca Apache Commons Exec en lugar de reinventarlos.


Ejemplo de Java 8:

public static String runCommandForOutput(List<String> params) { ProcessBuilder pb = new ProcessBuilder(params); Process p; String result = ""; try { p = pb.start(); final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); StringJoiner sj = new StringJoiner(System.getProperty("line.separator")); reader.lines().iterator().forEachRemaining(sj::add); result = sj.toString(); p.waitFor(); p.destroy(); } catch (Exception e) { e.printStackTrace(); } return result; }

Uso:

List<String> params = Arrays.asList("/bin/sh", "-c", "cat /proc/cpuinfo"); String result = runCommandForOutput(params);

Utilizo este código exacto y funciona bien para resultados de líneas individuales o múltiples. También podría agregar un controlador de flujo de errores.


En java 8 hay una secuencia agradable de lines () que puedes combinar con String.join y System.lineSeparator ():

try (BufferedReader outReader = new BufferedReader(new InputStreamReader(p.getInputStream())) { return String.join(System.lineSeparator(), outReader.lines().collect(toList())); // OR using jOOλ if you like reduced verbosity return Seq.seq(outReader.lines()).toString(System.lineSeparator()) }


Lea de InputStream . Puede agregar el resultado a un StringBuilder :

BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); StringBuilder builder = new StringBuilder(); String line = null; while ( (line = reader.readLine()) != null) { builder.append(line); builder.append(System.getProperty("line.separator")); } String result = builder.toString();


Para Java 7 y 8 esto debería funcionar:

private String getInputAsString(InputStream is) { try(java.util.Scanner s = new java.util.Scanner(is)) { return s.useDelimiter("//A").hasNext() ? s.next() : ""; } }

Luego en tu código, haz esto:

String stdOut = getInputAsString(p.getInputStream()); String stdErr = getInputAsString(p.getErrorStream());

Descaradamente lo robé de: ¿Cómo redirigir la salida de Process Builder a una cadena?


Puede hacer algo como esto:

private static BufferedReader getOutput(Process p) { return new BufferedReader(new InputStreamReader(p.getInputStream())); } private static BufferedReader getError(Process p) { return new BufferedReader(new InputStreamReader(p.getErrorStream())); } ... Process p = Runtime.getRuntime().exec(commande); BufferedReader output = getOutput(p); BufferedReader error = getError(p); String ligne = ""; while ((ligne = output.readLine()) != null) { System.out.println(ligne); } while ((ligne = error.readLine()) != null) { System.out.println(ligne); }


Solo agregue .inheritIO(); a la línea de construcción del proceso.

ES DECIR:

ProcessBuilder pb = new ProcessBuilder(script.sh).inheritIO();


Utilizando Apache Commons IOUtils puedes hacerlo en una sola línea:

ProcessBuilder pb = new ProcessBuilder("pwd"); String output = IOUtils.toString(pb.start().getInputStream());