浅析Java.lang.Process类 --- java中运行cmd命令

一、概述

Process类是一个java.lang包下的一个抽象类(所有的方法均是抽象的),封装了一个进程(即一个执行程序)。

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

ProcessBuilder.start() 和 Runtime.exec 方法创建一个本机进程,并返回 Process 子类的一个实例,该实例可用来控制进程并获取相关信息。

首先来看以下Process类的源码:

public abstract class Process {

public abstract OutputStream getOutputStream();

public abstract InputStream getInputStream();

public abstract InputStream getErrorStream();

public abstract int waitFor() throws InterruptedException;

public boolean waitFor(long timeout, TimeUnit unit)
       throws InterruptedException
   {
       long startTime = System.nanoTime();
       long rem = unit.toNanos(timeout);

       do {
           try {
               exitValue();
               return true;
           } catch(IllegalThreadStateException ex) {
               if (rem > 0)
                   Thread.sleep(
                       Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
           }
           rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
       } while (rem > 0);
       return false;
   }
   public abstract int exitValue();
   
   public abstract void destroy();
   
   public Process destroyForcibly() {
       destroy();
       return this;
   }
   
   public boolean isAlive() {
       try {
           exitValue();
           return false;
       } catch(IllegalThreadStateException e) {
           return true;
       }
   }
}    

从官方文档看下这些方法都是做什么的:

abstract void	destroy()
杀死子进程。
Process	destroyForcibly()
杀死子进程。
abstract int	exitValue()
返回子进程的退出值。
abstract InputStream	getErrorStream()
返回连接到子进程的错误输出的输入流。
abstract InputStream	getInputStream()
返回连接到子进程的正常输出的输入流。
abstract OutputStream	getOutputStream()
返回连接到子进程正常输入的输出流。
boolean	isAlive()
测试这个Process代表的子Process是否存活。
abstract int waitFor()
导致当前线程等待,如有必要,直到由此Process对象表示的进程已终止。
boolean	waitFor(long timeout, TimeUnit unit)
使当前线程等待,如有必要,直到此Process对象表示的子 Process已终止,或指定的等待时间过去。

二:如何创建process进程
1、每个 ProcessBuilder 实例管理一个进程属性集。start() 方法利用这些属性创建一个新的 Process 实例。start() 方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。
(processBuilder这个是JDK5中新添加的final类)
2、Runtime.exec() 方法创建一个本机进程,并返回 Process 子类的一个实例。

三:代码示例:

/**
 * @Author: chuxia0811
 * @Date: 2021/2/21 10:24
 * @Description :
 */
public class ProcessDemo {
    public static void main(String[] args) {
        try {
            Runtime rt = Runtime.getRuntime();

            Process pr = rt.exec("cmd /c del test111.txt",null,new File("E:"));

            BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream(), "GBK"));

            String line = null;

            while ((line = input.readLine()) != null) {
                System.out.println(line);
            }

            int exitVal = pr.waitFor();
            System.out.println("Exited with error code " + exitVal);

        } catch (Exception e) {
            System.out.println(e.toString());
            e.printStackTrace();
        }
    }
}

在E:盘目录下提前建一个test111.txt的文件,执行以上操作即可由java代码通过process类和cmd命令实现指定目录的文件的删除。

这里要注意一个坑:外部程序在执行结束后将会自动关闭,否则不管是字符流还是字节流均由于既读不到数据,又读不到流结束符而出现阻塞Java进程运行的情况。

而 cmd /c 就是告诉cmd环境进程,当执行完成后关闭自身。

这里要特别注意:Runtime.exec()这个方法,我们来看下源码:

public Process exec(String command, String[] envp, File dir)
        throws IOException {
        if (command.length() == 0)
            throw new IllegalArgumentException("Empty command");

        StringTokenizer st = new StringTokenizer(command);
        String[] cmdarray = new String[st.countTokens()];
        for (int i = 0; st.hasMoreTokens(); i++)
            cmdarray[i] = st.nextToken();
        return exec(cmdarray, envp, dir);
    }
public Process exec(String[] cmdarray, String[] envp, File dir)
        throws IOException {
        return new ProcessBuilder(cmdarray)
            .environment(envp)
            .directory(dir)
            .start();
    }

第一个参数command为要执行的命令,第二个参数envp为可以传递的String类型数组参数,第三个dir表示要切换或者要操作的目录,正如上面的demo代码:

Process pr = rt.exec("cmd /c del test111.txt",null,new File("E:"));

表示先将目录切换到E盘,然后执行del test111.txt 删除文件操作,操作完成后cmd /c 关闭退出进程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初夏0811

你的鼓励将是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值