1. ホーム
  2. java

[解決済み] ProcessBuilder。メインスレッドをブロックすることなく、起動したプロセスの標準出力と標準エラー出力を転送する。

2022-11-26 15:29:37

質問

JavaでProcessBuilderを使用して、以下のようなプロセスを構築しています。

ProcessBuilder pb = new ProcessBuilder()
        .command("somecommand", "arg1", "arg2")
        .redirectErrorStream(true);
Process p = pb.start();

InputStream stdOut = p.getInputStream();

さて、私の問題は次のようなものです。そのプロセスの標準出力や標準エラー出力をキャプチャし、それを System.out に非同期でリダイレクトしたい。プロセスとその出力リダイレクションはバックグラウンドで実行されるようにしたい。 今のところ、これを行うために私が見つけた唯一の方法は、手動で新しいスレッドを生成し、継続的に stdOut から継続的に読み込む新しいスレッドを手動で生成し、適切な write() のメソッドを呼び出します。 System.out .

new Thread(new Runnable(){
    public void run(){
        byte[] buffer = new byte[8192];
        int len = -1;
        while((len = stdOut.read(buffer)) > 0){
            System.out.write(buffer, 0, len);
        }
    }
}).start();

このアプローチは一応うまくいきますが、ちょっと汚い感じがします。その上、管理し正しく終了させるために、もう1つスレッドを与えてしまうのです。これを行うためのより良い方法はありますか?

どのように解決するのですか?

以下のような場合 Java 7 以降 については、Evgeniy Dorofeevの 回答 .

については Java 6 およびそれ以前 を作成し、使用します。 StreamGobbler :

StreamGobbler errorGobbler = 
  new StreamGobbler(p.getErrorStream(), "ERROR");

// any output?
StreamGobbler outputGobbler = 
  new StreamGobbler(p.getInputStream(), "OUTPUT");

// start gobblers
outputGobbler.start();
errorGobbler.start();

...

private class StreamGobbler extends Thread {
    InputStream is;
    String type;

    private StreamGobbler(InputStream is, String type) {
        this.is = is;
        this.type = type;
    }

    @Override
    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null)
                System.out.println(type + "> " + line);
        }
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}