Java执行操作系统命令-Process抽象类(1)

Java 8

Windows 10

Eclipse Version: 2022-09 (4.25.0)

--

 

序章

测试使用Java程序执行操作系统命令。ben发布于博客园

需要用到 抽象类Process:

// @since   JDK1.0
public abstract class Process {
//...
}

 在类注释中,提到了 ProcessBuilder、Runtime 两个类,用来生成Process对象——执行命令。ben发布于博客园

注,本文仅涉及Windows上的命令执行。

注,本文只测试执行Windows命令 cd、dir 两个命令。ben发布于博客园

 

测试目录:D:\javaprocess

 

涉及类:

java.lang.Process
java.lang.ProcessBuilder
java.lang.Runtime

 

执行命令:使用ProcessBuilder类

ProcessBuilder类 结构:ben发布于博客园

 

测试代码:输出执行后的 InputStream、ErrorStream 的内容。

	/**
	 * 测试:ProcessBuilder
	 */
	public static void test1(String... cmd) {
		cs.accept("start test1..");
		try {
			Process ps = new ProcessBuilder()
					.command(cmd)
					.start();
			
			cs.accept("1、InputStream:");
			processIs(ps.getInputStream());
			cs.accept("2、ErrorStream:");
			processIs(ps.getErrorStream());
			cs.accept("3、----END----");
		} catch (IOException e) {
			e.printStackTrace();
		}	
	}

	/**
	 * 输出InputStream的内容:字符集 GB2312
	 * @param is
	 * @throws IOException
	 */
	private static void processIs(InputStream is) throws IOException {
		final int size = 1024;
		byte[] buffer = new byte[size];

		Charset cset = Charset.forName("GB2312");
		cs.accept("cset=" + cset);
		
		StringBuffer sb = new StringBuffer();
		
		int ret = 0;
		int total = 0;
		while ((ret = is.read(buffer, 0, size)) > 0) {
			total += ret;
			String chunk = new String(buffer, 0, ret, cset);
			
			sb.append(chunk);
		}

		cs.accept("ret=" + ret + ", total=" + total);
		cs.accept("sb=" + sb.length() + ", content=" + sb);
		
		is.close();
	}

 

测试存在的目录

执行:test1("cmd", "/C", "dir", "d:\\javaprocess");ben发布于博客园

注意,这里的 cmd、/C 是必须的(Windows中)。

测试结果:目录存在,正常输出。

目录存在,执行正常,InputStream有数据,而ErrorStream没有数据。ben发布于博客园

 

测试不存在的目录

执行:test1("cmd", "/C", "dir", "d:\\javaprocessnull");ben发布于博客园

测试结果:目录不存,ErrorInput也要数据输出——找不到文件。

 

问题:这里的 InputStream 也有数据,是否可以将两者合并呢?ben发布于博客园

回答:可以。在start()之前执行 redirectErrorStream(true) 即可。

 

问题:测试时传入了4个参数,可以合并为一个吗?ben发布于博客园

回答:不可以。

执行 test1("cmd /C dir d:\\javaprocess");

测试结果:CreateProcess error=2, 系统找不到指定的文件。ben发布于博客园

 

执行命令:使用Runtime类

Runtime类 结构:

执行命令会用到其中的 exec函数,可以看到 exec函数有多个函数签名。

// 字符串的命令
public Process exec(String command) throws IOException {}
public Process exec(String command, String[] envp) throws IOException {}
public Process exec(String command, String[] envp, File dir) throws IOException {}

// 字符数组的命令
public Process exec(String cmdarray[]) throws IOException {}
public Process exec(String[] cmdarray, String[] envp) throws IOException {}
public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException {}

 

测试代码:test2(String cmd)

	/**
	 * 测试:Runtime.getRuntime().exec(...)
	 */
	public static void test2(String cmd) {
		cs.accept("start test2..cmd=" + cmd);
		try {
			Process ps = Runtime.getRuntime().exec(cmd);

			cs.accept("1、InputStream:");
			processIs(ps.getInputStream());
			cs.accept("2、ErrorStream:");
			processIs(ps.getErrorStream());
			cs.accept("3、----END----");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

注,会使用前面的 processIs(InputStream is) 函数。

 

测试存在的目录

执行:test2("cmd /C dir d:\\javaprocess");

测试结果:

注意,这里的命令是一个字符串。

 

测试不存在的目录

执行:test2("cmd /C dir d:\\javaprocessnull");

测试结果:

 
问题:这里的ErrorStream也有数据了,可以重定向到InputSteam吗?
回答:TODO
 

多条命令执行:Runtime类

场景:进入一个目录,再输出目录下的内容。

执行下面的语句可以实现吗?

test2("cmd /C cd d:\\javaprocess");
test2("cmd /C dir .");

回答:不可以。

两个Process是不同的进程——即不同的JVM。

 

执行多条命令,在使用Runtime类时,可以使用 && 符号。

执行:test2("cmd /C cd d:\\javaprocess && dir"); 或者 test2("cmd /C cd d:\\javaprocess && dir .");

测试结果:

 

问题:ProcessBuilder类 怎么执行多条命令呢?TODO

 

 

 

参考资料

1、java Process 执行批命令 cmd
by 老谭TYH
于 2022-11-22 12:18:50 发布
原文链接:https://blog.csdn.net/qq_30436011/article/details/127979994

2、

 

ben发布于博客园

 

posted @ 2022-12-19 20:11  快乐的凡人721  阅读(797)  评论(0编辑  收藏  举报