Java-执行系统命令&进程-入门篇

1 需求

  •  Runtime类 对应实物就是下面这个


  • 运行中直接运行cmd、notepad、mspaint、calc等是ok的
  • 运行中直接运行dir等会报错


  • Java通过Runtime.getRuntime().exec()创建子进程是入参字符串中首个程序,比如:cmd /c ping www.baidu.com,cmd.exe是Runtime.getRuntime().exec()创建的子进程,Process类的isAlive、exitValue、waitFor、destroy都是根据cmd.exe执行情况判断的,而不是PING.exe。

注意:如果想控制PING.EXE执行情况,直接exec("ping www.baidu.com')

  • idea64.exe
    • java.exe:主进程

      • cmd.exe:Runtime.getRuntime().exec()创建的子进程

        • PING.EXE


  • 需求:cmd命令、start命令
    • cmd命令 c参数、k参数
    • start命令 b参数

……

  • Runtime类
    • Process类
      • InputStream类
        • InputStreamReader类
          • BufferedReader类

  • 需求1:仅执行CMD命令,并不需要获取命令执行结果;
  • 需求2:执行CMD命令,同时只需要命令执行结果的某一行;
  • 需求3:执行CMD命令,需要命令执行结果所有数据;

  • 需求:判断子进程是否结束
    • 解决方案1:Process.isAlive()
    • 解决方案2:Process.exitValue()
  • 循环执行同一条CMD命令,第一次循环命令执行结束后,才允许执行第二次循环;
    • Process类的exitValue方法:非线程阻塞
    • Process类的waitFor方法:线程阻塞,如果子进程没有执行完毕,主线程会一直阻塞;
    • Process类的isAlive方法:
    • 参考资料:java runtime exec 输出

  • 需求:子进程等待
    • 解决方案1:Process.waitFor()
    • 解决方案2:Thread.sleep()
    • 解决方案3:timeout命令

  • 需求:停止子进程停止


  • 需求:停止子进程树


  • 需求:主进程和子进程死锁
    • 解决方案1:Process.getErrorStream()
  • 循环执行同一条CMD命令,第一次循环执行结束后,延迟N秒再执行第二次循环;
    • Windows的TIMEOUT命令:无法满足需求,使用Process类的getErrorStream()方法,获取错误信息如下:
      • 错误: 不支持输入重新定向,立即退出此进程。

  • 需求5:一次执行多条CMD命令,同时获取所有命令执行结果;

 


2 接口

Class Runtime

public class Runtime extends Object

java.lang.Object 
        java.lang.Runtime

  • Method Detail
    • public static Runtime getRuntime()
    • public void exit(int status)
    • public void addShutdownHook(Thread hook)
    • public boolean removeShutdownHook(Thread hook)
    • public void halt(int status)
    • public Process exec(String command) throws IOException
    • public Process exec(String command, String[] envp) throws IOException
    • public Process exec(String command, String[] envp, File dir) throws IOException
    • public Process exec(String[] cmdarray) throws IOException
    • public Process exec(String[] cmdarray, String[] envp) throws IOException
    • public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException
    • public int availableProcessors()
    • public long freeMemory()
    • public long totalMemory()
    • public long maxMemory()
    • public void gc()
    • public void runFinalization()
    • public void traceInstructions(boolean on)
    • public void traceMethodCalls(boolean on)
    • public void load(String filename)
    • public void loadLibrary(String libname)

3.1 示例代码:直接调起记事本,不需要获取命令执行结果

import java.io.*;

public class Test {
    public static void main(String[] args) throws IOException, InterruptedException {
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("notepad");
        process.waitFor();
        System.out.println(process.isAlive());
        System.out.println(process.exitValue());
    }
}

3.2 示例代码:执行命令,并且获取命令执行结果,但执行结果只有一行

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) {
        try {
            Process process = Runtime.getRuntime().exec("cmd /c adb shell getprop ro.build.fingerprint");
            BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.3 示例代码:执行命令,并且获取命令执行结果,但执行结果有多行

Runtime类

        Process类

                InputStream类:输入字节流

                        InputStreamReader类:字节流转化成字符流

                                BufferedReader类:使用缓冲流

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) throws IOException {

        // Runtime类
        Runtime runtime = Runtime.getRuntime();

        // Process类
        Process process = runtime.exec("ipconfig");

        // InputStream类
        InputStream inputStream = process.getInputStream();

        // InputStreamReader类
        InputStreamReader reader = new InputStreamReader(inputStream, "GBK");

        // BufferedReader类
        BufferedReader br = new BufferedReader(reader);

        String tmp = null;

        while ((tmp = br.readLine()) != null) {
            System.out.println(tmp);
        }
    }
}

3.4 示例代码:执行多条CMD命令,同时获取所有命令执行结果

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test {
    public static void main(String[] args) throws IOException {
        // Windows命令连接符:&&
        Process process = Runtime.getRuntime().exec("cmd /c dir&&ipconfig");
        InputStreamReader reader = new InputStreamReader(process.getInputStream(), "GBK");
        BufferedReader br = new BufferedReader(reader);
        String line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
    }
}

3.5 示例代码:顺序执行多条CMD命令,如果某条命令运行时间较长,需要等待完成后再执行下一条


3.X 示例:循环执行同一条CMD命令,第一次循环执行结束后,延迟N秒再执行第二次循环

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * 预期结果:输出1,延迟3秒,输出2。
 * 实际结果:timeout命令没有执行成功,调用getErrorStream(),获取错误信息如下:
 * 错误: 不支持输入重新定向,立即退出此进程。
 */
public class Test {
    public static void main(String[] args) {
        System.out.println(1);

        try {
            Process process = Runtime.getRuntime().exec("cmd /c timeout 10");
            // Process类的getInputStream()、getErrorStream()方法区别
            InputStreamReader ir = new InputStreamReader(process.getErrorStream(), "GBK");
            BufferedReader br = new BufferedReader(ir);
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            br.close();
            ir.close();

            // Process.exitValue()返回值0,命令执行正常;非0,命令执行异常
            System.out.println("cmd /c timeout 10 命令是否执行成功: " + process.exitValue());

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(2);
    }
}

 


3.X 获取反编译目录下所有java文件

疑问:dir到底可以只显示指定文件类型的文件吗?

答案:dir /b /s /o:n /a:a *.文件类型。该命令会显示当前目录及子目录中指定文件类型的所有文件,其中*.文件类型表示要查找的文件类型,例如*.txt表示查找所有扩展名为.txt的文本文件1。

  • dir /b /s *.txt:可以
  • dir path /b /s *.txt:不可以 
Process process = runtime.exec("cmd /c dir path /aa /b /s *.java");
Process process = runtime.exec("cmd /c dir path /aa /b /s java");
Process process = runtime.exec("cmd /c dir path /aa /b /s '*.java'");
Process process = runtime.exec("cmd /c dir path /aa /b /s | findstr .java");

4 参考资料

java Runtime.exec方法详解! - 知乎

Java 调用外部命令使用 waitFor() 方法阻塞或锁死 — 小小羊

java runtime exec 输出_[转]Java中Runtime.exec的一些事

Java程序调用命令行工具

Java 通过ProcessBuilder或Runtime.exec()调用(cmd/sh)系统命令方法代码

java执行cmd命令详解_山木枝的博客-CSDN博客_java执行cmd命令

Java 执行系统命令(cmd, bat, shell)_JimmyYang_MJ的博客-CSDN博客_java执行系统命令

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值