首页 > 基础资料 博客日记
java执行可执行文件
2024-03-02 15:00:05基础资料围观300次
概要
java执行bat或shell脚本的方式主要有三种方式
1、 使用Runtime.exec
2、 使用ProcessBuilder
3、 使用第三方的工具包commons-exec.jar
使用Runtime.exec
在 Java 中,使用 Runtime.exec() 方法执行外部可执行文件是一个常见的做法。但是,这种方法有一些限制和潜在的问题,比如它不太容易处理进程的输入/输出流。
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 类名称: ExeRunUtil.
* 类描述: 执行cmd命令
*/
public class ExeRunUtil{
private static Log log = LogFactory.getLog(ExeRunUtil.class);
/**
* 执行cmd命令
* @return 执行结果
*/
public static boolean exec(String[] command) {
Process proc;
try {
proc = Runtime.getRuntime().exec(command);
new StreamReader(proc,proc.getInputStream(),"Output" ).start();
new StreamReader(proc,proc.getErrorStream(),"Error").start();
} catch (IOException ex) {
log.error("IOException while trying to execute " + command,ex);
return false;
}
int exitStatus=1;
try {
exitStatus = proc.waitFor(); //等待操作完成
} catch (java.lang.InterruptedException ex) {
log.error("InterruptedException command: " + exitStatus,ex);
}
if (exitStatus != 0) {
log.error("Error executing command: " + exitStatus);
}
return (exitStatus == 0);
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* 获取exe执行信息
* @author shandongwill
*
*/
public class StreamReader extends Thread{
private final Log logger = LogFactory.getLog(getClass());
private InputStream is;
private String type;
private Process proc;
public StreamReader(Process proc,InputStream is, String type) {
this.is = is;
this.type = type;
this.proc=proc;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (type.equals("Error")) {
logger.error("Error:" + line);
proc.destroyForcibly();
} else {
logger.debug("Debug:" + line);
}
}
} catch (IOException ioe) {
logger.error(ioe);
}
}
}
使用ProcessBuilder
相比于 Runtime.exec(),ProcessBuilder 提供了更强大和灵活的功能,并允许你更好地控制进程的执行。
ProcessBuilder类用于创建操作系统进程,每个ProcessBuilder实例管理一个Process属性集合,通过start()方法用这些属性创建一个新的Process实例。
每个ProcessBuilder管理这些流程属性:
-
一个字符串列表形式的命令(command),表示要调用的外部程序文件及其参数(如果有的话).哪个字符串列表表示有效的操作系统命令取决于系统。
-
一个environment,它是从变量到值的依赖于系统的映射。初始值是当前进程环境的副本(参见System.getenv())。
-
工作目录(working directory),默认值是当前进程的当前工作目录,通常是由系统属性user.dir命名的目录。
-
标准输入的来源。默认情况下,子进程从管道读取输入。Java代码可以通过Process.getOutputStream()返回的输出流访问该管道。 但是,可以使用redirectInput将标准输入重定向到另一个源。在这种情况下,Process.getOutputStream()将返回一个空输出流,其中:写方法总是抛出IOException,close方法什么也不做。
-
标准输出和标准错误的目标。默认情况下,子流程将标准输出和标准错误写入管道。Java代码可以通过Process.getInputStream()和Process.getErrorStream()返回的输入流访问这些管道。但是,可以使用redirectOutput和redirectError将标准输出和标准错误重定向到其他目的地。在这种情况下,Process.getInputStream()和/或Process.getErrorStream()将返回一个空输入流。
6)redirectErrorStream属性。最初该属性为false,这意味着子流程的标准输出和错误输出被发送到两个独立的流,可以使用Process.getInputStream()和Process.getErrorStream()方法访问这两个流。如果该值被设置为true,则:
注意,这个类不是同步的。如果多个线程并发访问ProcessBuilder实例,并且至少有一个线程在结构上修改了其中一个属性,则必须在外部同步。
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class BatScriptExecutor {
public static void main(String[] args) {
// 创建一个 ProcessBuilder 实例
ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/c", "test.bat");
processBuilder.redirectErrorStream(true);
try {
// 启动进程
Process process = processBuilder.start();
// 读取进程的输出
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
// 等待进程结束
int exitCode = process.waitFor();
System.out.println("Exit code: " + exitCode);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
使用第三方工具包commons-exec.jar
commons-exec.jar 是 Apache Commons Exec 库的一部分,它提供了一个更强大和灵活的 API 来执行外部进程。与 Java 的标准 Runtime.exec() 和 ProcessBuilder 类相比,Apache Commons Exec 提供了更多的功能和更好的错误处理。
使用 Apache Commons Exec,你可以更容易地管理进程执行,包括设置进程的工作目录、环境变量、输入/输出流重定向、超时处理等。此外,它还提供了更好的错误消息和异常处理,帮助开发者更容易地诊断问题。
要使用 commons-exec.jar,你需要将其添加到你的项目依赖中。如果你使用 Maven,你可以在 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version> <!-- 使用你需要的版本号 -->
</dependency>
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
/**
* CMD工具类
*
* @author Administrator
*
*/
public class CmdUtils {
/**
* 执行命令
*
* @param command:命令
* @return String[]数组,String[0]:返回的正常信息;String[1]:返回的警告或错误信息
* @throws ExecuteException
* @throws IOException
*/
public static String[] handle(String command) throws ExecuteException, IOException {
// 接收正常结果流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// 接收异常结果流
ByteArrayOutputStream errorStream = new ByteArrayOutputStream();
CommandLine commandline = CommandLine.parse(command);
DefaultExecutor exec = new DefaultExecutor();
exec.setExitValues(null);
// 设置10分钟超时
ExecuteWatchdog watchdog = new ExecuteWatchdog(600 * 1000);
exec.setWatchdog(watchdog);
PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream, errorStream);
exec.setStreamHandler(streamHandler);
exec.execute(commandline);
// 不同操作系统注意编码,否则结果乱码
String out = outputStream.toString("UTF-8");
String error = errorStream.toString("UTF-8");
// 返回信息
String[] result = new String[2];
result[0] = out;
result[1] = error;
return result;
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: