ProcessBuilder & Process

1.ProcessBuilder介绍

此类用于创建操作系统进程。

每个 ProcessBuilder 实例管理一个进程属性集。start() 方法利用这些属性创建一个新的 Process 实例。start() 方法可以从同一实例重复调用,以利用相同的或相关的属性创建新的子进程。

每个进程生成器管理这些进程属性:

  • 命令 是一个字符串列表,它表示要调用的外部程序文件及其参数(如果有)。在此,表示有效的操作系统命令的字符串列表是依赖于系统的。例如,每一个总体变量,通常都要成为此列表中的元素,但有一些操作系统,希望程序能自己标记命令行字符串——在这种系统中,Java 实现可能需要命令确切地包含这两个元素。
  • 环境 是从变量 的依赖于系统的映射。初始值是当前进程环境的一个副本(请参阅 System.getenv())。
  • 工作目录。默认值是当前进程的当前工作目录,通常根据系统属性 user.dir 来命名。
  • redirectErrorStream 属性。最初,此属性为 false,意思是子进程的标准输出和错误输出被发送给两个独立的流,这些流可以通过 Process.getInputStream()Process.getErrorStream() 方法来访问。如果将值设置为 true,标准错误将与标准输出合并。这使得关联错误消息和相应的输出变得更容易。在此情况下,合并的数据可从 Process.getInputStream() 返回的流读取,而从 Process.getErrorStream() 返回的流读取将直接到达文件尾。

修改进程构建器的属性将影响后续由该对象的 start() 方法启动的进程,但从不会影响以前启动的进程或 Java 自身的进程。

大多数错误检查由 start() 方法执行。可以修改对象的状态,但这样 start() 将会失败。例如,将命令属性设置为一个空列表将不会抛出异常,除非包含了 start()

注意,此类不是同步的。如果多个线程同时访问一个 ProcessBuilder,而其中至少一个线程从结构上修改了其中一个属性,它必须 保持外部同步。

很容易启动一个使用默认工作目录和环境的新进程:

 Process p = new ProcessBuilder("myCommand", "myArg").start();
 

下面是一个利用修改过的工作目录和环境启动进程的例子:

 ProcessBuilder pb = new ProcessBuilder("myCommand", "myArg1", "myArg2");
 Map<String, String> env = pb.environment();
 env.put("VAR1", "myValue");
 env.remove("OTHERVAR");
 env.put("VAR2", env.get("VAR1") + "suffix");
 pb.directory("myDir");
 Process p = pb.start();
 

要利用一组明确的环境变量启动进程,在添加环境变量之前,首先调用 Map.clear()

 

2.程序实例

package com.siyuan.test.jdk;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Map;

public class ProcessBuilderTest {
	
	public static final String COMMAND_TEST_1 = "java -version";

	public static final String COMMAND_TEST_2 = "java -help";
	
	public static final String COMMAND_CMD = "cmd /c type D:\\test\\FileOutputTest.txt";
	
	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		ProcessBuilder pBuilder = new ProcessBuilder(COMMAND_TEST_1.split(" "));
		
		//command 是一个字符串列表,它表示要调用的外部程序文件及其参数
		System.out.println(pBuilder.command());
		//directory 当前进程的当前工作目录
//		System.out.println(pBuilder.directory());
		//environment 环境变量的值
//		Map<String, String> env = pBuilder.environment();
//		for (String key: env.keySet())
//			System.out.println(key + " : " + env.get(key));
		/*
		 * 最初,此属性为 false,意思是子进程的标准输出和错误输出被发送给两个独立的流,这些流可以通过
		 * Process.getInputStream() 和 Process.getErrorStream() 方法来访问。如果将值设置为
		 * true,标准错误将与标准输出合并。这使得关联错误消息和相应的输出变得更容易。在此情况下,合并的数据可从
		 * Process.getInputStream() 返回的流读取,而从 Process.getErrorStream()
		 * 返回的流读取将直接到达文件尾。
		 */
//		pBuilder.redirectErrorStream(true);
		//使用此进程生成器的属性启动一个新进程
		Process p = pBuilder.start();
		/*
		 * 重置command
		 * 不会影响已生成的Process实例p
		 */
		pBuilder.command(Arrays.asList(COMMAND_TEST_2.split(" ")));
		Process p2 = pBuilder.start();
		System.out.println("Command executed result p2: ");
		System.out.print(getResult(p2));
		System.out.println("Command executed error p2: ");
		System.out.print(getError(p2));
		System.out.println("Command executed result p: ");
		System.out.print(getResult(p));
		System.out.println("Command executed error p: ");
		System.out.print(getError(p));
		
		// CMD Command
		pBuilder.command(COMMAND_CMD.split(" "));
		Process p3 = pBuilder.start();
		System.out.println("Command executed result p3: ");
		System.out.print(getResult(p3));
		System.out.println("Command executed error p3: ");
		System.out.print(getError(p3));
	}
	
	public static String getResult(Process process) {
		BufferedReader resultReader = null;
		StringBuilder resultStr = new StringBuilder();
		try {
			resultReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
			String buf = null;
			while ((buf = resultReader.readLine()) != null) {
				resultStr.append(buf).append("\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (resultReader != null) {
				try {
					resultReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return resultStr.toString();
	}
	
	public static String getError(Process process) {
		BufferedReader errorReader = null;
		StringBuilder errorStr = new StringBuilder();
		try {
			errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
			String buf = null;
			while ((buf = errorReader.readLine()) != null) {
				errorStr.append(buf).append("\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (errorReader != null) {
				try {
					errorReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return errorStr.toString();
	}
	
}

 

3.参考资料

JDK文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值