Java程序执行Cmd指令所遇问题记录及解决方案

这篇是有关在编写Java程序执行Cmd指令时所遇到的问题记录,其中有一些是个人的理解,如有问题望不吝赐教,感谢❤

Windows 命令提示符(cmd.exe)是 Windows NT 下的一个用于运行 Windows 控制面板程序或某些 DOS 程序的shell程序

1.执行Cmd命令的两种方式

(1)RunTime.getRunTime().exec(多种重载方式) - 会得到一个Process对象通过其start()方法开启一个新进程以执行输入的指令。

这种方法就不多说了,最后这种形式还是用到第二种方式的方法(Java Api文档中也推荐使用第二种方式去创建一个Process对象):

* @see ProcessBuilder
* @since 1.3
*/
public Process exec(String[] cmdarray, String[] envp, File dir)
throws IOException {
return new ProcessBuilder(cmdarray)
.environment(envp)
.directory(dir)
.start();
}

(2).new ProcessBuilder().command(指令)

2.获取执行指令后的输出:

在这里就遇到点问题,

上面两种方式执行Windows自带的命令都没有什么问题(像Ping、Ipconfig)。但是当执行像“Java -version”这样的外部命令,其输出通过getInputStream()方法是拿不到的。

后来是通过参考网上资料,采用将子进程的输出重定向到文件中,再从文件中读取内容的方法:

// 外部程序的输出放到了错误信息输出流中,不将错误信息流输出到文件话,输出信息就看不到了😂
      pb.redirectErrorStream(true);
      // 把执行结果输出
      pb.redirectOutput(file);
      //等待语句执行完成,否则可能会读不到结果。
      pb.start().waitFor();
      InputStream in = new FileInputStream(file);
      br = new BufferedReader(new InputStreamReader(in,charsetName));
      String line = null;
      while ((line = br.readLine()) != null) {
        outPutResult.append(line).append("\n");
      }
      br.close();
      br = null;
      // 删除临时文件
      file.delete();

最新解决方法:刚写完这篇博客,就在想Java开发文档中这句“否则,如果使用ProcessBuilder.redirectErrorStream重定向子进程的标准错误,则此方法返回的输入流将接收合并的标准输出和子进程的标准错误。”(下面图片)怎么就没用呢,结果回头一看,文档是Java 8的,我跑的程序用的是Java 7的,把自己整笑了🙃,还在这一通瞎操作。
而至于为什么要将子进程标准输出和子进程的标准错误输出合并,可以看下小弟下面的拙见。

对于非Windows自带命令,可以这样写(不再需要借助文件):

public static StringBuilder runOutCmdTest(String command) {
    BufferedReader br = null;
    StringBuilder outPutResult = new StringBuilder();
    try{
    ProcessBuilder pb = new ProcessBuilder().command("cmd.exe", "/c", command);
    // 外部程序的输出放到了错误信息输出流中
    pb.redirectErrorStream(true);
    // 等待语句执行完成,否则可能会读不到结果。
    Process process = pb.start();
    process.waitFor();
    InputStream inputStream = process.getInputStream();
    br = new BufferedReader(new InputStreamReader(inputStream, "GBK"));
    String line;
    while ((line = br.readLine()) != null) {
      outPutResult.append(line).append("\n");
    }
    br.close();
    br = null;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return outPutResult;
  }

3.关于getInputStream ()无法得到子进程输出的原因

此方法获取的流是子进程正常输出流不包括异常错误信息流,Process对象将异常信息放在了ErrorStream中。这里可以试一下,会发现执行“Java -version”控制台输出的是红字,也就是异常信息。

emmm至于为什么Windows自带命令的正常输出会被视作异常信息,不太清楚,下次再looklook源码。

而按上面图片的最后一句,

4.一个调用指令例子

private static final String TEMP_FILE_PATH = "D:\\temp.txt";

  /**
   * 运行外部程序命令 无参数时调用
   * @param command 输入命令
   * @return 输出内容
   */
  public static StringBuilder runOutCmd(String command) {
    // 默认字符解析GBK
    return runOutCmd(command, null,"GBK");
  }

  /**
   * 运行外部程序命令 带参数
   * @param command 输入命令
   * @param args 输入参数
   * @return
   */
  public static StringBuilder runOutCmd(String command, List<String> args) {
    // 默认字符解析GBK
    return runOutCmd(command, args,"GBK");
  }

  /**
   * 运行外部程序命令 - 带参数并规定字符解析格式
   * @param args 输入参数
   * @param command 输入命令
   * @param charsetName 输出字符解析格式
   * @return
   */
  public static StringBuilder runOutCmd(String command, List<String> args, String charsetName) {
    BufferedReader br = null;
    StringBuilder outPutResult = new StringBuilder();
    try {
      // 新建一个用来存储子进程输出结果结果的缓存文件
      File file = new File(TEMP_FILE_PATH);
      if (!file.getParentFile().exists()) {
        file.getParentFile().mkdirs();
      }
      if (!file.exists()) {
        file.createNewFile();
      }
      List<String> execCommand = new LinkedList<>();
      if (args != null) {
        execCommand.addAll(args);
      }
      execCommand.add(0,command);
      execCommand.add(0,"/c");
      execCommand.add(0,"cmd.exe");
      ProcessBuilder pb = new ProcessBuilder().command(execCommand).inheritIO();
      // 外部程序的输出放到了错误信息输出流中
      pb.redirectErrorStream(true);
      // 把执行结果输出
      pb.redirectOutput(file);
      //等待语句执行完成,否则可能会读不到结果。
      pb.start().waitFor();
      InputStream in = new FileInputStream(file);
      br = new BufferedReader(new InputStreamReader(in,charsetName));
      String line = null;
      while ((line = br.readLine()) != null) {
        outPutResult.append(line).append("\n");
      }
      br.close();
      br = null;
      // 删除临时文件
      file.delete();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (br != null) {
        try {
          br.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return outPutResult;
  }

最新例子(不用借助文件):

/**
 * 运行外部程序命令 - 带参数并规定字符解析格式
 *
 * @param args    输入参数
 * @param command   输入命令
 * @param charsetName 输出字符解析格式
 * @return
 */
public static StringBuilder runOutCmd(String command, List<String> args, String charsetName) {
  BufferedReader br = null;
  StringBuilder outPutResult = new StringBuilder();
  try {
    List<String> execCommand = new LinkedList<>();
    if (args != null) {
      execCommand.addAll(args);
    }
    execCommand.add(0, command);
    execCommand.add(0, "/c");
    execCommand.add(0, "cmd.exe");
    ProcessBuilder pb = new ProcessBuilder().command(execCommand).inheritIO();
    // 外部程序的输出放到了错误信息输出流中
    pb.redirectErrorStream(true);
    //等待语句执行完成,否则可能会读不到结果。
    Process process = pb.start();
    process.waitFor();
    InputStream inputStream = process.getInputStream();
    br = new BufferedReader(new InputStreamReader(inputStream, charsetName));
    String line;
    while ((line = br.readLine()) != null) {
      outPutResult.append(line).append("\n");
    }
    br.close();
    br = null;
  } catch (Exception e) {
    e.printStackTrace();
  } finally {
    if (br != null) {
      try {
        br.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  return outPutResult;
}

ps:
1. inheritIO()作用:

意味着使用此方法,子进程的报错的异常信息也会在当前Java进程的控制台输出,而Process对象将非Windows命令的输出视为异常信息,那么非Windows命令的输出当使用了此方法的时候会在控制台输出。

2.字符解析格式问题:
输出出现乱码,与Cmd程序字符格式默认为GBK有关。
按实际情况修改流的解析格式就可以了:

 br = new BufferedReader(new InputStreamReader(in,charsetName));

到此这篇关于Java程序执行Cmd指令所遇问题记录及解决方案的文章就介绍到这了,更多相关Java程序执行Cmd指令内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 解决Java调用BAT批处理不弹出cmd窗口的方法分析

    常规调用方式:(这个肯定会弹出cmd窗口) 复制代码 代码如下: Runtime.getRuntime().exec("cmd.exe   /C   start   D:\\test.bat"); 解决不弹框只需要"start"后面加一个参数"/b"就行: 复制代码 代码如下: Runtime.getRuntime().exec("cmd.exe   /C   start   /b   D:\\test.bat"); 复制代码

  • java执行windows下cmd命令的方法

    本文实例讲述了java执行windows下cmd命令的方法.分享给大家供大家参考. 具体实现代码如下: 复制代码 代码如下: //获取运行时 Runtime rt = Runtime.getRuntime(); //获取进程 Process p = rt.exec(String[] cmdarray);//或者 Process p = rt.exec(String cmd); //如果p不为空,那么要清空 if(null!=p){destory p.destory(); p=null; } 例如

  • Java中如何调用cmd压缩文件

    今天在做一个java调用windows的压缩命令时遇到一奇怪问题代码如下: 复制代码 代码如下: String cmd ="C:/Program Files (x86)/WinRAR/rar.exe a c:/test.rar c:/test.log"; //System.out.println(cmd);Process proc = Runtime.getRuntime().exec(cmd); 以上代码在Xp,win7,windows server2003执行完全正常发现将代码转移

  • java运行windows的cmd命令简单代码

    我也不知道这个叫什么,就是比如我要打开我电脑的计算机,可以直接在命令行输入"calc"就可以了.现在用让代码去执行. 复制代码 代码如下: public static void main(String[] args) throws IOException {          Runtime.getRuntime().exec("calc");      } 结果如图: 因为是校园网,平时睡觉的时候喜欢把360wifi插在电脑上开着wifi,然后上床上玩手机,完了不

  • 一键设置java 环境变量 cmd下查看、修改(覆盖与添加)等说明

    上来就给点干货吧 安装JDK/安装JRE以及配置java环境变量对于java初学者来说是一件比较头疼的事情,这边分享一个简单的批处理命令,助大家一步完成JDK或者单独安装JRK的需求. 关键步骤: 1.新建一个.txt文档,复制附件一/附件二到文档中: 2.修改文档中的内容: 附件一:start /WAIT jdk-8u141-windows-i586.exe /qn INSTALLDIR=C:\Java\jdk1.8 附件二:start /WAIT jre-8u144-windows-i586

  • 将java程序打成jar包在cmd命令行下执行的方法

    前言 大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个jar包的程序入口.本文将给大家介绍java程序打成jar包在cmd命令行下执行的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 一.打包 二.修改配置文件是程序能够引用第三方jar包 1.新建一个文件夹,用来存储这个项目 ------------第三方jar包单独存在一个文件夹下面(这里放在了lib下面)(重点是lib要和weixin.jar同

  • Windows系统中Java调用cmd命令及执行exe程序的方法

    Java调用cmd命令,并输出显示信息: package com.anxin.cmd.test; import java.io.BufferedReader; import java.io.InputStreamReader; public class Command { public static void main(String[] args) { try { Runtime rt = Runtime.getRuntime(); Process pr = rt.exec("cmd /c di

  • Java程序执行Cmd指令所遇问题记录及解决方案

    这篇是有关在编写Java程序执行Cmd指令时所遇到的问题记录,其中有一些是个人的理解,如有问题望不吝赐教,感谢❤ Windows 命令提示符(cmd.exe)是 Windows NT 下的一个用于运行 Windows 控制面板程序或某些 DOS 程序的shell程序 1.执行Cmd命令的两种方式 (1)RunTime.getRunTime().exec(多种重载方式) - 会得到一个Process对象通过其start()方法开启一个新进程以执行输入的指令. 这种方法就不多说了,最后这种形式还是用

  • Java程序执行过程及内存机制详解

    本讲将介绍Java代码是如何一步步运行起来的,其中涉及的编译器,类加载器,字节码校验器,解释器和JIT编译器在整个过程中是发挥着怎样的作用.此外还会介绍Java程序所占用的内存是被如何管理的:堆.栈和方法区都各自负责存储哪些内容.最后用一小块代码示例来帮助理解Java程序运行时内存的变化. Java程序执行过程 步骤 1: 写源代码,源代码将以.java的文件格式保存在电脑硬盘中. 步骤 2: 编译器(compiler)检查是否存在编译期错误(例如缺少分号,关键字拼写错误等).若通过检测,编译器

  • python执行CMD指令,并获取返回的方法

    如下所示: result = os.popen('ps aux') res = result.read() for line in res.splitlines(): print line 以上这篇python执行CMD指令,并获取返回的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • python os.system执行cmd指令代码详解

    1.执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功. 2.在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码. os.system()方法是简单粗暴的执行cmd指令,没有办法获取到cmd输出的内容. 实例 # coding:utf-8 import os os.system("ls") Python如何使用OS模块调用cmd 在os模块中提供了两种调用 cmd 的方法,os.popen() 和 os

  • Java如何执行cmd命令

    目录 Java执行cmd命令 Java执行cmd命令总结 解释一下参数 总结 Java执行cmd命令 //当前绝对路径 System.out.println(IoUtil.read(Runtime.getRuntime().exec("cmd /c echo %cd%").getInputStream(), Charset.forName("gbk"))); //创建文件夹 System.out.println(IoUtil.read(Runtime.getRunt

  • Java执行cmd命令两种实现方法解析

    一般java在执行CMD命令时,通常是使用Runtime.getRuntime.exec(command)来执行的,这个方法有两种细节要注意: 1.一般执行方法,代码如下,这种方法有时执行exe时会卡在那里. //一般的执行方法,有时执行exe会卡在那 stmt要执行的命令 public static void executive(String stmt) throws IOException, InterruptedException { Runtime runtime = Runtime.g

  • 在Python中执行cmd

    目录 1.使用os.system()方法 2.使用os.popen()方法 3.使用subprocess.Popen() 1.使用os.system()方法 os.system用来执行cmd指令,在cmd输出的内容会直接在控制台输出,返回结果为0表示执行成功. 示例代码: # coding:utf-8 import os os.system("ls") PS:os.system()方法是简单粗暴的执行cmd指令,没有办法获取到cmd输出的内容. PPS:os.system()方法在调用

  • Java程序去调用并执行shell脚本及问题总结(推荐)

    摘要: 该文章来自阿里巴巴技术协会(ATA)精选集 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发. java开发的特点就是我们可以很早地进行TDDL, METAQ 等等地对接: 而脚本开发的特点就是在进行批处理的时候非常方便. 背景 我们在开发过程中,大部分是java开发, 而在文本处理过程中,主要就是脚本进行开发. java开发的特点就是我们可以很早地进行TDDL, METAQ 等等地对接: 而脚本开发的特点就是在进行批处理的时候非常方便. 前阵子我

  • 使用Jacoco获取 Java 程序的代码执行覆盖率的步骤详解

    Jacoco是Java Code Coverage的缩写,顾名思义,它是获取Java代码执行覆盖率的一个工具,通常用它来获取单元测试覆盖率.它通过分析Java字节码来得到代码执行覆盖率,因此它还可以分析任何基于JVM的语言(如Croovy.Kotlin)的覆盖率.本文不讨论如何用Jacoco获取单元测试的代码覆盖率,而是从Jacoco的原理出发,介绍如何通过Jacoco获取SIT或者UAT的测试覆盖率.更准确来讲,是获取一个应用执行过的代码占总代码的比率.包括字节码指令覆盖率,分支覆盖率,圈复杂

随机推荐