1/17/2011

Java Runtime exec

使用Java執行外部指令( ls, pwd....) OSX環境執行的很好,但在windows環境確整個掛住跑不動(Java真的有跨平台嗎?),搞了一下午才弄清楚。

原本程式極為單純容易,但是會在windows 環境掛住!

最後才發現原來祕密寫在Process Java Doc說明裡:

The methods that create processes may not work well for special processes on certain native platforms, such as native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows, or shell scripts. The created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams ( Process.getOutputStream() , Process.getInputStream() , Process.getErrorStream() ). The parent process uses these streams to feed input to and get output from the subprocess. 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.

程式改寫

新增ProcessHandler處理 limited buffer size for standard input and output streams

[code lang="java"] public class ProcessHandler extends Thread { InputStream inpStr; final StringBuffer output; public ProcessHandler(InputStream inpStr, StringBuffer output) { this.inpStr = inpStr; this.output = output; } public void run() { try { InputStreamReader inpStrd = new InputStreamReader(inpStr); BufferedReader buffRd = new BufferedReader(inpStrd); String line = null; while ((line = buffRd.readLine()) != null) { output.append(line).append("\n"); } buffRd.close(); } catch (Exception e) { System.out.println(e); } } } } [/code]

主程式修正

[code lang="java"] ... Process p = Runtime.getRuntime().exec(getCommandLine()); StringBuffer msgBuilder = new StringBuffer(); ProcessHandler inputStream = new ProcessHandler(p.getInputStream(), msgBuilder); ProcessHandler errorStream = new ProcessHandler(p.getErrorStream(), msgBuilder); inputStream.start(); errorStream.start(); p.waitFor(); ... [/code]

雖然解決在OSX、Windows環境執行外部指令問題 ,另一地方比較有趣問題Java怎麼知道我有沒有處理Process.getOutputStream() , Process.getInputStream() , Process.getErrorStream() ?

No comments:

Post a Comment