Java Runtime


1.exe-t「...」というexeファイルがあり、結果をコンソールに出力します.プログラムで呼び出し、出力結果を取得したいです.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {

	public static void main(String[] args) {

		Process cmdProcess = null;
		BufferedReader movieBr = null;
		BufferedReader cmdBr = null;
		BufferedWriter wholeBw = null;
		BufferedWriter primaryBw = null;

		String[] cmd = { "title.exe", "-t", "" };
		String movieLine, cmdLine;

		try {
			movieBr = new BufferedReader(
					new FileReader(
							"movies.dat"));

			wholeBw = new BufferedWriter(new FileWriter(
					"whole.info"));
			primaryBw = new BufferedWriter(new FileWriter(
					"primary.info"));

			while ((movieLine = movieBr.readLine()) != null) {
				String[] tmp = movieLine.split("::");
				
				System.out.println(tmp[0]);
				
				cmd[2] = tmp[1];

				cmdProcess = Runtime.getRuntime().exec(cmd);
				cmdBr = new BufferedReader(new InputStreamReader(
						cmdProcess.getInputStream()));  //1
				boolean flag = false;
				while ((cmdLine = cmdBr.readLine()) != null) {
					wholeBw.write(cmdLine);
					if (flag) {
						primaryBw.write(tmp[0] + "::" + cmdLine.trim() + "
"); flag = false; } if (cmdLine.equals("Director:")) { flag = true; } } //2 cmdProcess.waitFor(); } wholeBw.flush(); primaryBw.flush(); } catch (Exception e) { e.printStackTrace(); } finally{ try{ if(movieBr != null){ movieBr.close(); } if(wholeBw != null){ wholeBw.close(); } if(primaryBw != null){ primaryBw.close(); } } catch (Exception e){ System.out.println("close stream error!"); e.printStackTrace(); } } } }

主にcmdProcess.waitForおよびcmdProcess.getInputStream()の処理に注意する
waitFor関数の役割は,cmdProcessが終了するまで主スレッドをブロックすることである. getInputStream()は、入力ストリームとしてcmdProcessの出力ストリームを得る.
最初はずっと悩んでいましたが、cmdProcess.waitFor()は位置1に置くべきか位置2に置くべきか2.最初は位置2に置くと、ストリームの内容を読むときにcmdProcessがまだ実行されていないのではないかと思っていましたが、結果が出力されず、ストリームの中に何も読めませんでした.
後に実験を行い、cmdBrがcmdProcess.getInputStream()をキャプチャしたため、cmdBrを呼び出すと、cmdProcessがまだ出力されていないか、出力がまだ終了していない場合、ここでブロックされることが分かった.cmdProcessが出力され、終了子が出力されるまで.
次は実験方法です.Cプログラムを書いてhello worldを出力します.
#include<iostream>
using namespace std;
int main()
{
	int n=INT_MAX;
	while(n--);
	cout<<"hello world"<<endl;
}
それからテストプログラムで、このexeファイルを呼び出します.
public class TTT {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Process cmdProcess = null;
		String[] cmd = { "test.exe" };
		try {
			cmdProcess = Runtime.getRuntime().exec(cmd);
			BufferedReader cmdBr = new BufferedReader(new InputStreamReader(
					cmdProcess.getInputStream()));
			System.out.println(cmdBr.readLine());   // line 3
			System.out.println("main process: hello world");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
結果の出力が開始されたのは数秒後です
hello world
main process: hello world
line 3にブロックがなければmain process:hello worldを先に出力するに違いない.test.exeがループしているので(オペレーティングシステムの授業では、プロセス実行の前後順を仮定することはできませんが、ここで十分です).