ProcessBuilder は使いたくはないけど・

ProcessBuilder は使いたくはないけど致し方ない場面がありますね。

ProcessBuilder

ProcessBuilder は標準出力や標準エラー出力から読み出さずにいるとロックしたりしてあんまり気軽に使えなくて、いつも以下のようなの作るはめになるので書いとこ・・

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ProcessBroker {
    private List<String> command = new ArrayList<String>();
    private StringBuilder stdout = new StringBuilder();
    private StringBuilder stderr = new StringBuilder();

    public ProcessBroker(String... command) {
        this.command.addAll(Arrays.asList(command));
    }

    public int execute() throws IOException, InterruptedException {
        Process process = new ProcessBuilder(command).start();
        new StreamReaderThread(process.getInputStream(), stdout).start();
        new StreamReaderThread(process.getErrorStream(), stderr).start();
        return process.waitFor();
    }

    public String getStdout() {
        return stdout.toString();
    }

    public String getStderr() {
        return stderr.toString();
    }

    class StreamReaderThread extends Thread {
        InputStream inputStream;
        StringBuilder output;

        StreamReaderThread(final InputStream inputStream, StringBuilder output) {
            this.inputStream = inputStream;
            this.output = output;
        }

        @Override public void start() {
            try {
                readStream(inputStream, output);
            } catch (IOException e) {
                output.append(e.getMessage());
            }
        }

        private void readStream(InputStream inputStream, StringBuilder sb)
                throws IOException {
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                while ((line = reader.readLine()) != null)
                    sb.append(line + "\n");
            } finally {
                reader.close();
            }
        }
    }
}

使い方は

こんな感じ

ProcessBroker pb = new ProcessBroker("java -version".split(" "));
pb.execute();
System.out.println(pb.getStdout());
System.out.println(pb.getStderr());

あと、ProcessBuilder の引数にはコマンドを「java -version」であれば、
String[]{"java","version"} のように分けて渡さなければならないので注意。


追記:
パイプ等使用する場合は以下のように使用します。

ProcessBroker pb = new ProcessBroker("sh,-c,ps -ef | grep java".split(","));