龙哥网

龙哥网

如何使用 Java 中执行 Windows 的 CMD 命令
2022-03-01

如何使用 Java 中执行 Windows 的 CMD 命令

  • 核心代码
  • 完整代码

  在 CMD 中执行 BAT 脚本对用户不友好,而且有安全隐患,因此笔者编写了一些可以在 Java 中执行 Windows 的 CMD 命令的 API。

核心代码

  • 执行单条命令
package org.wangpai.demo;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.experimental.Accessors;

/** * @since 2021-12-21 */
@Accessors(chain = true)
public class WinCmd { 
    private Charset cmdCharset;

    @Getter(AccessLevel.PROTECTED)
    private Process process;

    private String originalCommandMsg;

    private String output;

    private int exitValue;

    private WinCmd() { 
        super();
    }

    public static WinCmd getInstance() { 
        return new WinCmd();
    }

    /** * 如果调用本方法时,本方法会阻塞调用线程,直到命令执行结束 * * @since 2021-12-21 */
    public int getExitValue() throws Exception { 
        if (this.process == null) { 
            throw new Exception("需要先执行命令后才能获取退出码");
        }

        this.exitValue = process.waitFor();
        return this.exitValue;
    }

    public String getOutput() throws Exception { 
        if (this.process == null) { 
            throw new Exception("需要先执行命令后才能获取输出");
        }
        if (this.output != null) { 
            return this.output;
        }

        var inputStream = process.getInputStream();
        // 获取操作系统(命令行)的字符集
        this.cmdCharset = Charset.forName((String) System.getProperties().get("sun.jnu.encoding"));
        // 将输出按行分成多个字符串。这原本不是想要的操作,但这没有办法
        var lines = new BufferedReader(new InputStreamReader(
                inputStream, this.cmdCharset)).lines();
        this.output = lines.collect(Collectors.joining(System.lineSeparator()));
        // 将每行字符串以换行符拼接,还原出原始信息
        return this.output;
    }

    public String getCommand() throws Exception { 
        if (this.originalCommandMsg == null) { 
            throw new Exception("还没有输入命令");
        }

        return this.originalCommandMsg;
    }

    public WinCmd execute(String command) throws Exception { 
        return this.exec(command);
    }

    private WinCmd exec(String originalCommand) throws IOException { 
        this.output = null;
        this.originalCommandMsg = originalCommand;
        this.process = Runtime.getRuntime().exec(this.originalCommandMsg);
        return this;
    }
}

  • 执行多条命令
package org.wangpai.demo;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/** * @since 2021-12-21 */
public class WinBat { 
    private int commandNum;

    private Charset cmdCharset;

    private String[] originalCommandMsg;

    private Process[] processArray;

    private String[] outputs;

    private int[] exitValues;

    private WinBat() { 
        super();
    }

    public static WinBat getInstance() { 
        return new WinBat();
    }

    public String getIntegrationOutput() throws Exception { 
        if (this.processArray == null) { 
            throw new Exception("需要先执行命令后才能获取输出");
        }

        if (this.outputs == null) { 
            // 获取操作系统(命令行)的字符集
            this.cmdCharset = Charset.forName((String) System.getProperties().get("sun.jnu.encoding"));
            this.outputs = new String[this.commandNum];
            InputStream inputStream;
            for (int index = 0; index < this.commandNum; ++index) { 
                inputStream = this.processArray[index].getInputStream();
                // 将输出按行分成多个字符串。这原本不是想要的操作,但这没有办法
                var linesOutput = new BufferedReader(new InputStreamReader(
                        inputStream, this.cmdCharset)).lines();
                // 将每行字符串以换行符拼接,还原出原始信息
                this.outputs[index] = linesOutput.collect(Collectors.joining(System.lineSeparator()));
            }
        }

        var stream = Stream.of(this.outputs);
        // 多加一个空行作不同命令输出之间的分隔
        return stream.collect(Collectors.joining(System.lineSeparator() + System.lineSeparator()));
    }

    public String getIntegrationCommand() throws Exception { 
        if (this.originalCommandMsg == null) { 
            throw new Exception("还没有输入命令");
        }

        var stream = Stream.of(this.originalCommandMsg);
        return stream.collect(Collectors.joining(System.lineSeparator()));
    }

    public String[] getOriginalCommand() throws Exception { 
        if (this.originalCommandMsg == null) { 
            throw new Exception("还没有输入命令");
        }

        return this.originalCommandMsg;
    }

    /** * 如果调用本方法时,本方法会阻塞调用线程,直到命令执行结束 * * @since 2021-12-21 */
    public int[] getExitValues() throws Exception { 
        if (this.processArray == null) { 
            throw new Exception("需要先执行命令后才能获取退出码");
        }

        this.exitValues = new int[this.commandNum];
        for (int index = 0; index < this.commandNum; ++index) { 
            this.exitValues[index] = this.processArray[index].waitFor();
        }

        return this.exitValues;
    }

    /** * 如果调用本方法时,本方法会阻塞调用线程,直到命令执行结束 * * @since 2021-12-21 */
    public int getLastExitValues() throws Exception { 
        if (this.processArray == null) { 
            throw new Exception("需要先执行命令后才能获取退出码");
        }

        var exitValues = this.getExitValues();
        return exitValues[this.commandNum - 1];
    }

    private WinBat exec(String[] originalCommand) throws Exception { 
        this.outputs = null;
        this.originalCommandMsg = originalCommand;
        this.commandNum = originalCommand.length;
        this.processArray = new Process[this.commandNum];

        for (int index = 0; index < this.commandNum; ++index) { 
            this.processArray[index] = WinCmd.getInstance()
                    .execute(this.originalCommandMsg[index]).getProcess();
        }

        return this;
    }

    public WinBat execute(String[] command) throws Exception { 
        return this.exec(command);
    }
}

完整代码

  已上传至 GitCode 中,可免费下载:https://gitcode.net/wangpaiblog/20220110-win_cmd

免责声明
本站部分资源来源于互联网 如有侵权 请联系站长删除
龙哥网是优质的互联网科技创业资源_行业项目分享_网络知识引流变现方法的平台为广大网友提供学习互联网相关知识_内容变现的方法。