博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java通过Process运行外部子程序
阅读量:2055 次
发布时间:2019-04-28

本文共 2740 字,大约阅读时间需要 9 分钟。

 

Java中ProcessBuilder.start()和Runtime.exec()方法都被用来创建一个操作系统进程(执行命令行操作),并返回 Process 子类的一个实例,该实例可用来控制进程状态并获得相关信息。

Process类

Process类提供了从进程输入、输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。

Java中创建的Process子进程没有自己的终端或控制台;它的所有标准IO重定向到父进程,父进程使用这些流来提供到子进程的输入和获得从子进程的输出:

  • 子进程的stdin通过Process的getOutputStream()获取
  • 子进程的stdout通过Process的getInputStream()获取
  • 子进程的stderr通过Process的getErrorStream()获取

因为平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子进程的输出流或输入流出现失败(或未读取),则可能导致子进程阻塞,甚至产生死锁。

当没有Process对象的更多引用时(在Java中离开作用域时),不是杀掉子进程,而是继续异步执行子进程。若要杀掉子进程,需通过destroy()函数来实现。

Runtime.exec方式

Runtime.getRuntime()提供了多个重载方法以启动子进程:可接受一个单独的字符串(通过空格来分隔可执行命令程序和参数);也可以接受字符串数组参数。

命令行启动

通过windows的cmd /c+要运行的命令可以方便的启动所需的程序。通过此命令也可以一次执行多条命令:

cmd /c cd c:/mypath && start mypro.exe

通过命令行执行启动程序时,程序启动完成后命令行会退出,所以Java中对应的Process也会完成退出。

public void runCommand(String strCmd){    // cmd /c cd c:\tmp && start test.ext    String strRun = "cmd /c";    strRun += strCmd;    try{        Process proc = Runtime.getRuntime().exec(strRun);        if(!proc.waitFor(1, TimeUnit.SECONDS)){            System.out.println("Wait timeout!!!");        }    }    catch(Exception ex){        ex.printStackTrace();    }}

直接启动

明确知晓要运行的程序与对应参数的情况下,也可直接通过exec启动进程。此时,若进程通过stdout有输出,则需要通过getInputStream来读取(否则,若缓冲区满时,则子进程会被阻塞掉);若没有,则不需要处理。

public void runApp(String strExe, String strParam, String strPath) {    Thread thr = new Thread(() -> {        String strRun = Paths.get(strPath, strExe).toString();        strRun += " " + strParam;        File fPath = new File(strPath);        try {            Process proc = Runtime.getRuntime().exec(strRun, null, fPath);            InputStream inStream = proc.getInputStream();            try (InputStreamReader reader = new InputStreamReader(inStream);                    BufferedReader br = new BufferedReader(reader);) {                String line;                while ((line = br.readLine()) != null) {                    System.out.println(line);                }            }        } catch (Exception ex) {            ex.printStackTrace();        }    });    thr.start();}

ProcessBuilder方式

ProcessBuilder实例管理一个进程属性集,ProcessBuilder的start()方法利用这些属性创建一个新的Process实例。start()方法可以从同一实例重复调用,以利用相同或者相关的属性创建新的子进程。

public void getIPv4Address() {    ProcessBuilder pbGet = new ProcessBuilder("ipconfig", "/all");    try {        Process process = pbGet.start();        try (InputStreamReader inReader = new InputStreamReader(process.getInputStream(), "GBK");                BufferedReader br = new BufferedReader(inReader);) {            String line;            while ((line = br.readLine()) != null) {                if (line.indexOf("IPv4") != -1) {                    System.out.println(line);                }            }        }    } catch (IOException e) {        e.printStackTrace();    }}

转载地址:http://pgnlf.baihongyu.com/

你可能感兴趣的文章
剑指offer 4.替换空格
查看>>
剑指offer 5.从尾到头打印链表
查看>>
剑指offer 6.用两个栈实现队列
查看>>
剑指offer 7.旋转数组的最小数字
查看>>
剑指offer 8-11.斐波那契数列 跳台阶 变态跳台阶 矩形覆盖
查看>>
剑指offer 12.二进制中1的个数
查看>>
剑指offer 13.数值的整数次方
查看>>
剑指offer 14.调整数组顺序使奇数位于偶数前面
查看>>
剑指offer 15.链表中倒数第k个节点
查看>>
剑指offer 16.反转链表
查看>>
剑指offer 17.合并两个排好序的链表
查看>>
剑指offer 18.树的子结构
查看>>
剑指offer 19.二叉树的镜像
查看>>
剑指offer 20.顺时针打印矩阵
查看>>
剑指offer 21.包含min函数的栈
查看>>
剑指offer 23.从上往下打印二叉树
查看>>
剑指offer 25.二叉树中和为某一值的路径
查看>>
剑指offer 26. 数组中出现次数超过一半的数字
查看>>
剑指offer 27.二叉树的深度
查看>>
剑指offer 29.字符串的排列
查看>>