Runtime.getRuntime().exec() 输出流阻塞的解决办法

Runtime.getRuntime().exec() 输出流阻塞的解决方法
转自:http://blog.****.net/xiaoanian/article/details/5922394
java中用Runtime.getRuntime().exec() 调用外部程序, 获取"标准输出流", 老是阻塞. 在网上找了找, 觉得应该是"错误输出流"的问题. 果然, 为"错误输出流"单开一个线程读取之, "标准输出流"就不再阻塞了. 源码如下:


[java] view plaincopy
/**执行外部程序,并获取标准输出*/ 
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那样执行较为复杂的命令. 比如, 输出流的重定向, 如:

[java] view plaincopy
Runtime.getRuntime.exec("XX.exe YY.doc > ZZ.txt"); 


他会立即返回, 不会去执行. 但是我们可以这样做, 能够完成于cmd中一样的工作:

[c-sharp] view plaincopy
Runtime.getRuntime.exec("cmd /c XX.exe YY.doc > ZZ.txt"); 


其中 /c 就是"执行后面字符串的命令". 这样就OK了,但同时还是要注意"错误输出流"的问题,依然要单开一个线程读取.否则一样会阻塞的.