在模拟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("\n");
            }

            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();
        }
    }
}

Java如何执行操作系统的CMD命令行的更多相关文章

  1. 在cmd命令行使用Maven Archetype插件 generate命令创建简单的java web项目

    前提: 1.下载apache-maven:https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache ...

  2. 在windows下使用cmd命令行对java文件进行编译和执行

    windows下利用cmd命令行可以调用jdk里的javac.exe和java.exe对java文件进行编译和执行,前提是jdk已成功安装并正确配置相关环境变量 相关配置链接:java基础学习总结—— ...

  3. paip.执行shell cmd 命令uapi java php python总结

    paip.执行shell cmd 命令uapi java php python总结 作者Attilax  艾龙,  EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:h ...

  4. Atitit.执行cmd 命令行 php

    Atitit.执行cmd 命令行 php 1. 执行cmd 命令行,调用系统命令的基础 1 1.1. 实际执行模式 1 1.2. 空格的问题 1 1.3. 中文路径的问题,程序文件读取编码设置 1 1 ...

  5. [Java] cmd命令行如何切换目录

    cmd.exe是微软Windows系统基于WINDOWS上的命令解释程序,类似于微软的DOS操作系统.cmd.exe是一个32位的命令行程序,运行在Windows NT/2000/XP/2003/vi ...

  6. CMD命令行提示被禁用的情况下如何继续使用命令行工具执行命令

    1.直接在Windows搜索 左下 输入要执行的 CMD 命令单句.多句同时执行没有试出来. 暂时记录这一条.2016-12-20

  7. Windows 如何在cmd命令行中查看、修改、删除与添加环境变量

    转自:http://www.cnblogs.com/saptechnique/archive/2013/02/17/2914222.html 首先明确一点: 所有的在cmd命令行下对环境变量的修改只对 ...

  8. 如何在cmd命令行中查看、修改、删除与添加环境变量,语法格式例子:set path;echo %APPDATA%

    如何在cmd命令行中查看.修改.删除与添加环境变量 首先明确一点: 所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改.也就是说当关闭此cmd命令行窗口后,将不再起作用.永久性修 ...

  9. cmd命令行带参启动程序

    cmd命令行带参启动程序 有一些程序不支持被直接启动,编写代码时,我们可以通过Process类来启动某个进程(某个软件),在不用代码调从而启动某个软件时,windows系统下,通常我们会用到cmd命令 ...

随机推荐

  1. vue-router 在项目中的使用

    一.下载vue-router npm install vue-router --save 二.编码 1.在项目中新建文件夹 router/index.js /* * 路由对象模块 * */ impor ...

  2. tkinter为多个窗口设置相同的icon报错

    import threading import tkinter from PIL import Image, ImageTk def show_window(): window = tkinter.T ...

  3. B+树的算法(java实现)

    定义 一颗m阶B+树满足以下几个条件: 1.除根节点外的节点的关键字个数最大为m-1,最小为m/2 2.除叶节点外的每个节点的孩子节点的数目为该节点关键字个数加一,这些孩子节点的的关键字的范围与父节点 ...

  4. 【转】Git使用教程之远程仓库

    1.远程仓库 在了解之前,先注册github账号,由于你的本地Git仓库和github仓库之间的传输是通过SSH加密的,所以需要一点设置: 第一步:创建SSH Key.在用户主目录下,看看有没有.ss ...

  5. 1.监控软件zabbix-入门

    入门学习 首先要明白zabbix的读音(音同zæbix),主要进行网络相关的监控.它是一个基于WEB界面展示提供分布式系统监控的一款开源软件. zabbix有两部分:zabbix server和zab ...

  6. cross validation交叉验证

    交叉验证是一种检测model是否overfit的方法.最常用的cross validation是k-fold cross validation. 具体的方法是: 1.将数据平均分成k份,0,1,2,, ...

  7. java web spring异步方法

    在项目中,时常会有异步调用的需求 web.xml配置 <servlet> <description>spring mvc servlet</description> ...

  8. nrm : 无法加载文件 C:\Users\TANG\AppData\Roaming\npm\nrm.ps1,因为在此系统上禁止运行脚本。

    1.win+s 搜索powershell 以管理身份运行 2.使用set-ExecutionPolicy RemoteSigned命令将计算机上的执行策略更改为 RemoteSigned,输入Y确定 ...

  9. 7 Exciting Uses of Machine Learning in FinTech

    https://rubygarage.org/blog/machine-learning-in-fintech Machine learning (ML) has moved from the per ...

  10. LG5357 「模板」AC自动机(二次加强版) AC自动机+fail树

    问题描述 LG5357 题解 不是fail树的AC自动机复杂度是假的. 把AC自动机搞出来,建立Trie树,树上爆搜一遍就好了. \(\mathrm{Code}\) #include<bits/ ...