Java通过Process运行外部子程序

Process类

Runtime.exec方式

ProcessBuilder方式

 

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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值