javaでは、別プロセスを起動するための機能がJDK1.4まではjava.lang.Runtimeクラスに、JDK1.5からはjava.lang.ProcessBuilderクラスに備わっています。JDK1.5から導入されたProcessBuilderは使い方も簡単なので、JDK1.4以前しか使えない制約がないならば、ProcessBuilderを中心に使っていくことになるでしょう。
execメソッドです。コマンドライン・オプションや環境変数の引渡し方法によって複数がオーバーロードされています。
Runtimeクラスのインスタンスは、newで生成するのではなく、RuntimeクラスのstaticメソッドgetRuntime()で取得します。
起動するプログラム名とプログラムに渡す引数を指定します。引数はいくつでも記述することができます。JDK1.5で導入された可変長引数が利用されています。
ProcessBuilder pb = new ProcessBuilder("notepad.exe", "test.txt"); try { Process p = pb.start(); int ret = p.waitFor(); System.out.println("process exited with value : " + ret); } catch (IOException e) { // start()で例外が発生 e.printStackTrace(); } catch (InterruptedException e) { // waitFor()で例外が発生 e.printStackTrace(); }
起動するコマンドへPATHが通っていなくても、フルパスで指定することは出来ます。
ProcessBuilder pb = new ProcessBuilder( "C:/Program Files/OpenOffice.org1.1.4/program/soffice.exe", "-writer" ); // 以下略
GUIツール(アプリケーション)とは違い、CUIツール(コマンド環境でのツール)の場合、実行結果が標準出力に出されるものが大半です。この場合、標準出力を呼び出し側で拾ってあげねばなりません。少々面倒ですが、以下のように記述します。
ProcessBuilder pb = new ProcessBuilder( "unzip", "-l", "c:/Documents and Settings/torutk/tmp/junit3.8.1.zip" ); try { Process p = pb.start(); InputStream stdIn = p.getInputStream(); InputStream errIn = p.getErrorStream(); int c; while ((c = stdIn.read()) != -1) { System.out.print((char)c); } stdIn.close(); while ((c = errIn.read()) != -1) { System.out.print((char)c); } errIn.close(); int ret = p.waitFor(); System.out.println("process exited with value : " + ret); } catch (IOException e) { // start()で例外が発生 または、Streamで例外発生 e.printStackTrace(); } catch (InterruptedException e) { // waitFor()で例外が発生 e.printStackTrace(); } finally { stdIn.close(); errIn.close(); }
この例では単純にInputStreamを素で使い、read()で1バイトずつ処理しているので、結構遅いです。BufferedInputStreamでラップしてreadLine()で行単位で処理するともっと速くなるでしょう。
指定した文字列を外部プロセスとして実行する簡単なランチャープログラム。