[Java How To Programming] [Home on 246net] [Home on Alles net]
Powered by SmartDoc

外部プロセスの起動(Runtime#exec)

TAKAHASHI, Toru
torutk@alles.or.jp

目次

外部プロセスを制御するクラス

javaでは、別プロセスを起動するための機能がJDK1.4まではjava.lang.Runtimeクラスに、JDK1.5からはjava.lang.ProcessBuilderクラスに備わっています。JDK1.5から導入されたProcessBuilderは使い方も簡単なので、JDK1.4以前しか使えない制約がないならば、ProcessBuilderを中心に使っていくことになるでしょう。

Runtimeクラス

execメソッドです。コマンドライン・オプションや環境変数の引渡し方法によって複数がオーバーロードされています。

Runtimeインスタンスの取得

Runtimeクラスのインスタンスは、newで生成するのではなく、RuntimeクラスのstaticメソッドgetRuntime()で取得します。

execメソッド各種

ProcessBuilderクラス

PATHの通っているコマンドを引数付で呼び出す

起動するプログラム名とプログラムに渡す引数を指定します。引数はいくつでも記述することができます。JDK1.5で導入された可変長引数が利用されています。

notepad起動
    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が通っていなくても、フルパスで指定することは出来ます。

OpenOffice起動
    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()で行単位で処理するともっと速くなるでしょう。

サンプル

簡単ランチャー

指定した文字列を外部プロセスとして実行する簡単なランチャープログラム。