Как перенаправить вывод Process Builder в строку?
Я использую следующий код для запуска построителя процессов.Я хочу знать, как я могу перенаправить его вывод в строку.
ProcessBuilder pb = new ProcessBuilder(System.getProperty("user.dir")+"/src/generate_list.sh", filename);
Process p = pb.start();
Я попытался с помощью ByteArrayOutputStream
но, похоже, это не сработало.
8 ответов
Читать от InputStream
. Вы можете добавить вывод в 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();
Использование Apache Commons IOUtils вы можете сделать это в одну строку:
ProcessBuilder pb = new ProcessBuilder("pwd");
String output = IOUtils.toString(pb.start().getInputStream());
вы можете сделать что-то вроде этого:
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);
}
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;
}
использование:
List<String> params = Arrays.asList("/bin/sh", "-c", "cat /proc/cpuinfo");
String result = runCommandForOutput(params);
Я использую этот точный код и он работает хорошо для одного или нескольких результатов. Вы также можете добавить обработчик потока ошибок.
для Java 7 и 8 это должно работать:
private String getInputAsString(InputStream is)
{
try(java.util.Scanner s = new java.util.Scanner(is))
{
return s.useDelimiter("\A").hasNext() ? s.next() : "";
}
}
затем в вашем коде сделайте следующее:
String stdOut = getInputAsString(p.getInputStream());
String stdErr = getInputAsString(p.getErrorStream());
я бесстыдно украл это у:как перенаправить вывод Process Builder в строку?
после попытки обработки различных случаев (обработка как stderr, так и stdout и не блокирование любого из них, завершить процесс после таймаута, правильно экранируя косые черты, кавычки, специальные символы, пробелы,.... ) Я сдался и нашел Apache Commons Exec https://commons.apache.org/proper/commons-exec/tutorial.html это, кажется, делает все эти вещи довольно хорошо.
Я рекомендую всем, кому нужно вызвать внешний процесс в java использовать библиотеку Apache Commons Exec вместо того, чтобы изобретать ее снова.
просто добавить .inheritIO();
к строке process builder.
IE:
ProcessBuilder pb = new ProcessBuilder(script.sh).inheritIO();
в java 8 есть хороший поток lines (), который вы можете объединить со строкой.регистрация и система.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())
}