有一个exe文件,用法是 1.exe -t "...." , 它会把结果输出到控制台。 我想在程序里面调用它,并拿到输出结果。
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() + "\n"); 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(); } } } }
waitFor函数的作用是让主线程阻塞,直到cmdProcess结束。 getInputStream()得到cmdProcess的输出流,作为输入流。
开始一直在纠结,cmdProcess.waitFor()是应该放到位置1还是位置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
如果在line3没有阻塞的话,那么肯定是先输出main process: hello world的。因为test.exe循环了那么就(虽然我们操作系统课上,老师说不能假定进程执行的先后顺序,但是用在这里已经足够了)。