Runtime.getRuntime().exec() 輸出流阻塞的解決方法
阿新 • • 發佈:2019-01-23
Java中用Runtime.getRuntime().exec() 呼叫外部程式, 獲取"標準輸出流", 老是阻塞. 在網上找了找, 覺得應該是"錯誤輸出流"的問題. 果然, 為"錯誤輸出流"單開一個執行緒讀取之, "標準輸出流"就不再阻塞了. 原始碼如下:
/**執行外部程式,並獲取標準輸出*/ public static String excuteCmd_multiThread(String[] cmd,String encoding) { BufferedReader bReader=null; InputStreamReader sReader=null; try { Process p = Runtime.getRuntime().exec(cmd); /*為"錯誤輸出流"單獨開一個執行緒讀取之,否則會造成標準輸出流的阻塞*/ Thread t=new Thread(new InputStreamRunnable(p.getErrorStream(),"ErrorStream")); t.start(); /*"標準輸出流"就在當前方法中讀取*/ BufferedInputStream bis = new BufferedInputStream(p.getInputStream()); if(encoding!=null && encoding.length()!=0) { sReader = new InputStreamReader(bis,encoding);//設定編碼方式 } else { sReader = new InputStreamReader(bis,"GBK"); } bReader=new BufferedReader(sReader); StringBuilder sb=new StringBuilder(); String line; while((line=bReader.readLine())!=null) { sb.append(line); sb.append("/n"); } bReader.close(); p.destroy(); return sb.toString(); } catch(Exception e) { e.printStackTrace(); return ErrorString; } finally { } } /**讀取InputStream的執行緒*/ class InputStreamRunnable implements Runnable { BufferedReader bReader=null; String type=null; public InputStreamRunnable(InputStream is, String _type) { try { bReader=new BufferedReader(new InputStreamReader(new BufferedInputStream(is),"UTF-8")); type=_type; } catch(Exception ex) { } } public void run() { String line; int lineNum=0; try { while((line=bReader.readLine())!=null) { lineNum++; //Thread.sleep(200); } bReader.close(); } catch(Exception ex) { } } }
另外, Runtime.getRuntime().exec() 還有一些侷限性, 就是無法像cmd那樣執行較為複雜的命令. 比如, 輸出流的重定向, 如:
Runtime.getRuntime.exec("XX.exe YY.doc > ZZ.txt");
他會立即返回, 不會去執行. 但是我們可以這樣做, 能夠完成於cmd中一樣的工作:
Runtime.getRuntime.exec("cmd /c XX.exe YY.doc > ZZ.txt");
其中 /c 就是"執行後面字串的命令". 這樣就OK了,但同時還是要注意"錯誤輸出流"的問題,依然要單開一個執行緒讀取.否則一樣會阻塞的.