zoukankan      html  css  js  c++  java
  • Java如何执行操作系统的CMD命令行

    【本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究。若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!】

    在模拟cmd调用Python时遇到一些情况,这类问题可以归类为“超时,阻塞”等,问题原因:

    Process p=Runtime.getRuntime().exec(String[] cmd);
    

    Runtime.exec方法将产生一个本地的进程,并返回一个Process子类的实例,该实例可用于控制进程或取得进程的相关信息。 由于调用Runtime.exec方法所创建的子进程没有自己的终端或控制台,因此该子进程的标准IO(如stdin,stdou,stderr)都通过p.getOutputStream(),p.getInputStream(),p.getErrorStream() 方法重定向给它的父进程了.用户需要用这些stream来向子进程输入数据或获取子进程的输出。

    例如:Runtime.getRuntime().exec("ls") 另外需要关心的是Runtime.getRuntime().exec()中产生停滞(阻塞,blocking)的问题? 这个是因为Runtime.getRuntime().exec()要自己去处理stdout和stderr的输出, 就是说,执行的结果不知道是现有错误输出(stderr),还是现有标准输出(stdout)。你无法判断到底那个先输出,所以可能无法读取输出,而一直阻塞。 例如:你先处理标准输出(stdout),但是处理的结果是先有错误输出(stderr), 一直在等错误输出(stderr)被取走了,才到标准输出(stdout),这样就产生了阻塞。

    解决办法:

    用两个线程将标准输出(stdout)和错误输出(stderr)。

    完整代码:

    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    /**
     * Create by yster@foxmail.com 2018/11/9 0009 22:28
     */
    public class ExecuteCmd {
        /**
         * 执行外部程序,并获取标准输出
         */
        public static String execute(String[] cmd,String... encoding) {
            BufferedReader bufferedReader;
            InputStreamReader inputStreamReader;
            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) {
                    inputStreamReader = new InputStreamReader(bis, encoding[0]);// 设置编码方式
                } else {
                    inputStreamReader = new InputStreamReader(bis, "utf-8");
                }
                bufferedReader = new BufferedReader(inputStreamReader);
    
                StringBuilder sb = new StringBuilder();
                String line;
    
                while ((line = bufferedReader.readLine()) != null) {
                    sb.append(line);
                    sb.append("
    ");
                }
    
                bufferedReader.close();
                p.destroy();
                return sb.toString();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
    }
    
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    
    class InputStreamRunnable implements Runnable {
        private BufferedReader bReader = null;
    
        InputStreamRunnable(InputStream is, String type) {
            try {
                bReader = new BufferedReader(new InputStreamReader(new BufferedInputStream(is), "UTF-8"));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    
        public void run() {
            String line;
            int num = 1;
            try {
                while ((line = bReader.readLine()) != null) {
                    //System.out.println("---->"+String.format("%02d",num++)+" "+line);
                }
                bReader.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    

    版权声明

    【本文版权归微信公众号"代码艺术"(ID:onblog)所有,若是转载请务必保留本段原创声明,违者必究。若是文章有不足之处,欢迎关注微信公众号私信与我进行交流!】

  • 相关阅读:
    Hadoop集群(三) Hbase搭建
    Hadoop集群(二) HDFS搭建
    Hadoop集群(一) Zookeeper搭建
    Redis Cluster 添加/删除 完整折腾步骤
    Redis Cluster在线迁移
    Hadoop分布式HA的安装部署
    Describe the difference between repeater, bridge and router.
    what is the “handover” and "soft handover" in mobile communication system?
    The main roles of LTE eNodeB.
    The architecture of LTE network.
  • 原文地址:https://www.cnblogs.com/onblog/p/13043397.html
Copyright © 2011-2022 走看看