在模拟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. mssql SQL Server 2008 阻止保存要求重新创建表的更改问题的设置方法

    解决方法: 工具-〉选项-〉左侧有个 设计器-〉表设计器和数据库设计器 -> 阻止保存要求重新创建表的更改(右侧) 把钩去掉即可.

  2. Vue.js项目实战-多语种网站(租车)

    首先来看一下网站效果,想写这个项目的读者可以自行下载哦,地址:https://github.com/Stray-Kite/Car: 在这个项目中,我们主要是为了学习语种切换,也就是右上角的 中文/En ...

  3. 以一道ctf学习python脚本

    今天做了省赛初赛的ctf比赛,过程真是忐忑,奋战了6个小时(本来是三个小时的,哈哈哈哈). 不说了! 不说了! 说多了都是泪~ 看题吧,题目就是一道流量分析题,里面有一段icmp包,icmp包的ttl ...

  4. 理解Java方法增强

    在实际开发中,我们往往需要对某些方法进行增强,常用的方法增强的方式有三种. 类继承 .方法覆盖 必须控制对象创建,才能使用该方式 装饰者模式方法加强 必须和目标对象实现相同接口或继续相同父类,特殊构造 ...

  5. JVM源码分析之MetaspaceSize和MaxMetaspaceSize的区别

    JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永久代. ...

  6. Bootstrap Table列宽拖动的方法

    在之前做过的一个web项目中,前端表格是基于jQuery和Bootstrap Table实现的,要求能利用拖动改变列宽,现将实现的过程记录如下: 1. Bootstrap Table可拖动,需要用到它 ...

  7. element-ui的tag组件关闭事件失效的原因

    问题如上,原因是忘了加上一个函数 @close="handleClose(tag)" <el-tag :key="tag" v-for="tag ...

  8. Linux设备管理(四)_从sysfs回到ktype【转】

    转自:https://www.cnblogs.com/xiaojiang1025/archive/2016/12/21/6202298.html sysfs是一个基于ramfs的文件系统,在2.6内核 ...

  9. NVIDIA-SMI参数解析

    第一栏的Fan:N/A是风扇转速,从0到100%之间变动,这个速度是计算机期望的风扇转速,实际情况下如果风扇堵转,可能打不到显示的转速.有的设备不会返回转速,因为它不依赖风扇冷却而是通过其他外设保持低 ...

  10. Jquery ajax 同步阻塞引起的UI线程阻塞的坑(loading图片显示不出来,layer.load延迟)

    今天想做一个点击地市用ajax重新获取数据刷新页面功能,因为ajax属于耗时操作,想在获取数据且加载页面时显示加载遮罩层,结果发现了ajax的好多坑. 例如如上栗子,我想点击按钮让遮罩层显示,ajax ...