Java 使用Runtime.getRuntime.exec 和 ProcessBuilder 調用外部命令

這幾天在做來到公司以來的第一個項目,一個可以生成statcvs report的web小工具

昨天一天糾結於調用外部命令後程序阻塞的問題,直到剛剛終於解決。

我要調用的外部指令是 cvs log 生成某個項目源碼的cvs日誌文件

一開始我用的是Runtime.getRuntime.exec(cmd)方法,

Process process = Runtime.getRuntime().exec("cmd");

OutputStream os = process.getOutputStream();

InputStream es = process.getErrorStream();

runCommand(os,"cd " + projectPath + "\n");

runCommand(os, "E:" + "\n");

runCommand(os, "cvs log -d \"" + date1 + "<" + date2 + "\" > " + logFilePath + "\n");


但是使用這個方法調用指令總是會運行一會兒就阻塞住。

後來我又改用ProcessBuilder, 同樣出現了阻塞的問題,我google了一下,發現問題在於:

都有自己的標準輸入、標準輸出、標準錯誤輸出,對於某些 依賴於OS的進程,可能其輸出緩衝區很小,如果不能及時的讀出(標準輸出、標註錯誤輸出),將導致進程不能正常退出。

我的程序中有對標準輸出做了處理,但是cvs log指令還有錯誤輸出,於是我在處理標準輸出前新建一個線程讀取錯誤輸出緩衝區:

Process process = builder.start();

			InputStream is = process.getInputStream();
			InputStream es = process.getErrorStream();
			
			ErrorOutputReader errReader = new ErrorOutputReader(es);
			
			errReader.start();
			
			byte[] re=new byte[128];

			while (is.read(re)!=-1) {

				String temp = new String(re, 0, len(re),"UTF-8");

				System.out.println(temp);

				result = result+ temp;

			}
這樣之後程序正常結束了,但讓人惱火的是ProcessBuilder 不支持輸出重定向指令,而我用上面的方法,即讀取字節碼再轉爲string存入文件生成的log文件卻不準確,導致statcvs無法解析。


絕望之際我又轉投支持重定向指令Runtime.getRuntime.exec(cmd),它能夠準確生成log文件,而且也不用去care 標準輸出的問題,我只要將錯誤輸出緩衝區讀完就行,

但是奇怪的是程序依舊阻塞,我百思不得其解,  糾結了一天始終卡在那裏, 我想我腦袋都阻塞了。

後來我想 難道是標準輸入的問題, 於是我加入了一句process.getOutoutStream().close(), 居然就神奇地不阻塞了。


這是什麼原因?  莫非這個close()功能類似於命令行裏輸入ctrl+z?


總之問題就這樣解決了。  好交差去嘍!!!







Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章