☕
[メモ] Javaで外部コマンドを実行する
たまに使うけど、だいたい忘れてるのでメモ。
とりあえずシンプルに
とりあえずこんな感じ。それにしてもInputStreamをStringにするのは昔に比べて随分らくになったよなー.
public static void main(String[] args) throws Exception {
var result = execCommand("ls", "-l");
System.out.print(result.get("stdout"));
System.err.print(result.get("stderr"));
System.out.println("status: " + result.get("status"));
}
Map<String, String> execCommand(String... cmds) throws IOException, InterruptedException {
var result = new HashMap<String, String>();
var proc = Runtime.getRuntime().exec(cmds);
result.put("stdout", toString(proc.getInputStream()));
result.put("stderr", toString(proc.getErrorStream()));
result.put("status", Integer.toString(proc.waitFor()));
return result;
}
String toString(InputStream input){
try (var xs = new BufferedReader(new InputStreamReader(input)).lines()) {
return xs.collect(Collectors.joining(System.lineSeparator()));
}
}
中身は下記辺りを参照すると詳しく書いてある。
逐次表示
上記のコードだとよく考えたら逐次表示されないのでコールバックを取る形にちょっと修正。クラス定義とかちゃんとすればもう少しシンプルなAPIになると思うけど、とりあえずこんな感じで。
Map<String, String> execCommand(Consumer<String> stdProc, Consumer<String> errProc, String... cmds)
throws IOException, InterruptedException {
var result = new HashMap<String, String>();
var proc = Runtime.getRuntime().exec(cmds);
result.put("stdout", read(proc.getInputStream(), (s) -> System.out.println(s)));
result.put("stderr", read(proc.getErrorStream(), (s) -> System.err.println(s)));
result.put("status", Integer.toString(proc.waitFor()));
return result;
}
String read(InputStream input, Consumer<String> callback) {
var sb = new StringBuilder();
try (Stream<String> s = new BufferedReader(new InputStreamReader(input)).lines()) { // 自動close
s.map((l) -> {
sb.append(l);
sb.append(System.lineSeparator());
return l;
}).forEach(callback);
}
return sb.toString();
}
Happy Hacking!
Discussion