Java調用外部進程并攔截輸入輸出流--Java IDE Console解密(下篇)
Posted on 2007-01-15 23:00 網路冷眼@BlogJava 閱讀(4873) 評論(6) 編輯 收藏 所屬分類: Java 、Java SE
幾乎所有的Java 集成開發環境都需要調用外部進程進行Java程序的構建,編譯,運行和調試,Eclipse,NetBeans,JBuilder和Intellij IDLE概莫例外。在執行過程中,將提示信息以黑色全部打印在控制臺里,將異常和錯誤以紅色方式打印。以非常醒目交互體驗讓程序員遠離枯燥和乏味。
現在讓我們以Eclipse為例來看看它如何工作的,以揭開它神秘面紗,探究隱藏在后面的秘密。
上篇主要介紹了JAVA IDE Console通過采用Runtime.getRuntime.exec()執行外部程序后,將返回一個Process對象. Process對象能返回三個流:
getInputStream(),對應Process程序的標準輸出流。
getErrorStream(), 對應Process程序的標準錯誤輸出流。
getOutputStream();對應Process程序的標準輸入流。
函數名之所以與Process程序的方向相反,原因是站在Java Host程序的角度講的。
現在我們應用此原理來仿真IDE 執行外部程序的過程。
列表1:ConsoleSimulator.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
/**
* Class for console simulation
*
* @author lewhwa
*/
public class ConsoleSimulator implements Runnable {
private volatile boolean isStop = false ;
private static final int INFO = 0 ;
private static final int ERROR = 1 ;
private InputStream is;
private int type;
/** Creates a new instance of StreamInterceptor */
public ConsoleSimulator(InputStream is, int type) {
this .is = is;
this .type = type;
}
public void run() {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String s;
try {
while (( ! isStop) && (s = reader.readLine()) != null ) {
if (s.length() != 0 ) {
if (type == INFO) {
System.out.println( " INFO> " + s);
} else {
System.err.println( " ERROR> " + s);
}
try {
Thread.sleep( 10 );
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void stop() {
isStop = true ;
}
public static void main(String[] args) throws IOException,
InterruptedException {
// Process child = Runtime.getRuntime().exec("run.bat");
Process child = Runtime.getRuntime().exec( " java -classpath bin helloworld.Test " );
OutputStream os = child.getOutputStream();
InputStream stdin = child.getInputStream(); //
InputStream stderr = child.getErrorStream();
Thread tIn = new Thread( new ConsoleSimulator(stdin, INFO));
Thread tErr = new Thread( new ConsoleSimulator(stderr, ERROR));
tIn.start();
tErr.start();
int result = child.waitFor();
tIn.join();
tErr.join();
if (result == 0 ) {
System.out.println( " SUCCESS! " );
} else {
System.out.println( " FAILED! " );
}
}
}
外部Bat文件:
列表2
cmd.exe / C / Q copy
javac
cmd.exe / C tree
rem c:\Designer_v5. 1 .0_win32_x86.exe c:\Designer_v5. 1 .0_win32_x861.exe
time / t
測試Java類Test.java
列表3:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**Test Class
* @author lewhwa
*
*/
public class Test {
public static void main(String[] args) throws IOException {
FileReader fir = new FileReader("src/helloworld/Test1.java");
BufferedReader br = new BufferedReader(fir);
String s;
while((s=br.readLine())!=null){
System.out.println(s);
}
fir.close();
}
}
當ConsoleSimulator程序執行外部的run.bat時,輸出如圖1所示:
圖1
當ConsoleSimulator程序執行外部的java test正常時,輸出如圖2所示:

圖2
當ConsoleSimulator程序執行外部的java test發生異常時,輸出如圖3所示:
圖3
綜上,雖然沒有在自己的GUI里將stdout和stderr進行說明,只是用ERROR>提示符和INFO>提示符進行演示,但是完全IDE Console的原理。對ConsoleSimulator稍加修改,完全放入到自己的應用程序當中去。
在我們進行Java程序開發的過程當中,可能涉及到其它的應用程序,借助這種技術,可以很好利用它們,將它們集成到自己的應用當中,將極大地縮短開發周期,何樂而不為呢!