ProcessBuilderの使い方

JavaDoc読んでもよく分かんなくてはまった><。4,5時間これに嵌り続けたので晒しておこう。間違ってる点は指摘してくださいませ。

ŠO•”ƒvƒƒOƒ‰ƒ€‚ðŽÀs‚µ‚ÄŒ‹‰Ê‚ðŽæ“¾‚·‚é(Javaƒ}ƒXƒ^[)のページを参考にしました。(ありがとうございます!)ポイントは以下の通り。

  • 今回のはWindows XP上の話で他のOSの事はとりあえず横において置いてます。
  • 1コマンドの実行は1Processで。
  • ProcessBuilder#command(String...)は "コマンド名","引数1","引数2"...と言うように指定する。(JavaDocから類推すると複数コマンド実行できるように見えるじゃんか><)
  • 環境変数はSystem.getenv()からコピーしてくれるような期待をさせてくれるJavaDocだけど、そんなことしてあげないから!っていう感じ。Windows版JREは意外にツンなのか。
  • という事で、環境変数PATHも自前で設定しなければならないようだ。
  • でもC:\Windows\System32にはパスが通っているらしい。
  • 環境変数の設定はProcessBuilder#environment().put("PATH",環境変数で指定したいパス);
  • 環境変数で指定したいパスはもちろん「;」で区切って複数指定できるらしい。
  • Process#getInputStream()やProcess#getErrorStream()はもちろん同一スレッドで受け取ってたら「まとめて出力」しか出来ないので、ストリームで扱う意味がなくなってまう。参考リンク先のようにThreadを作るのが正解。
  • でもStringWriter#printlnを使っちゃうのは速度的に良いのかもわかんないけど、System.outやSystem.errに直接流し込んじゃう方が素のコンソールに近い動きをするはずだからいいんじゃなかろうか。

サンプルコードのCatcherをいじってみる。

class Catcher extends Thread {
  Reader in;
  PrintWriter out;
  public Catcher(Reader in,PrintWriter out) {
    this.in = in;
    this.out = out;
  }

  public void run() {
    int c;
    try {
      while ((c = in.read()) != -1) {
        out.write((char)c);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }

  }

}

こうしておくとこんな感じでストリームを監視するスレッドを作成できる。

new Catcher(p.getInputStream(),System.out);
new Catcher(p.getErrorStream(),System.err);

繰り返しますが、変なところはじゃんじゃんつっこんで下さい!よく分からんの。ProcessBuilderは。