幾乎所有的Java 集成開發(fā)環(huán)境都需要調(diào)用外部進程進行Java程序的構(gòu)建,編譯,運行和調(diào)試,Eclipse,NetBeans,JBuilder和Intellij IDLE概莫例外。在執(zhí)行過程中,將提示信息以黑色全部打印在控制臺里,將異常和錯誤以紅色方式打印。以非常醒目交互體驗讓程序員遠離枯燥和乏味。
現(xiàn)在讓我們以Eclipse為例來看看它如何工作的,以揭開它神秘面紗,探究隱藏在后面的秘密。
上篇主要介紹了JAVA IDE Console通過采用Runtime.getRuntime.exec()執(zhí)行外部程序后,將返回一個Process對象. Process對象能返回三個流:
getInputStream(),對應(yīng)Process程序的標準輸出流。
getErrorStream(), 對應(yīng)Process程序的標準錯誤輸出流。
getOutputStream();對應(yīng)Process程序的標準輸入流。
函數(shù)名之所以與Process程序的方向相反,原因是站在Java Host程序的角度講的。
現(xiàn)在我們應(yīng)用此原理來仿真IDE 執(zhí)行外部程序的過程。
列表1:ConsoleSimulator.java
package
helloworld;
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
time
/
t
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:
package helloworld;
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程序執(zhí)行外部的run.bat時,輸出如圖1所示:

圖1
當ConsoleSimulator程序執(zhí)行外部的java test正常時,輸出如圖2所示:
圖2
當ConsoleSimulator程序執(zhí)行外部的java test發(fā)生異常時,輸出如圖3所示:

圖3
綜上,雖然沒有在自己的GUI里將stdout和stderr進行說明,只是用ERROR>提示符和INFO>提示符進行演示,但是完全IDE Console的原理。對ConsoleSimulator稍加修改,完全放入到自己的應(yīng)用程序當中去。
在我們進行Java程序開發(fā)的過程當中,可能涉及到其它的應(yīng)用程序,借助這種技術(shù),可以很好利用它們,將它們集成到自己的應(yīng)用當中,將極大地縮短開發(fā)周期,何樂而不為呢!