1. 程式人生 > >Runtime.getRuntime().exec() 輸出流阻塞的解決方法

Runtime.getRuntime().exec() 輸出流阻塞的解決方法

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了,但同時還是要注意"錯誤輸出流"的問題,依然要單開一個執行緒讀取.否則一樣會阻塞的.