Runtime、ProcessBuilder的区别(Java中,两种方法来启动其他程序)

80 篇文章 4 订阅
9 篇文章 0 订阅

目录

■Runtime、ProcessBuilder 区别:

■Java中提供了两种方法来启动其他程序

■代码

・Runtime

・ProcessBuilder

■类的方法

・Process.waitFor()方法

・Process.getErrorStream()方法

・Process.redirectErrorStream(true)方法:

■可运行代码

・java代码   (直接运行)

・运行的bat代码

・结果

・java代码   (运行,并获取运行的程序 的 输出)

・对应的bat代码 (有输出)

・运行结果(可以获得输出)

■Java Process.exitValue & Process.waitFor()

■其它资料整理

■参考


=================

■Runtime、ProcessBuilder 区别:

ProcessBuilder.start() 和 Runtime.exec()传递的参数有所不同,
・Runtime.exec()可接受一个单独的字符串,这个字符串是通过空格来分隔可执行命令程序和参数的;
・ProcessBuilder的构造函数是一个字符串列表或者数组。列表中第一个参数是可执行命令程序,其他的是命令行执行是需要的参数。

■Java中提供了两种方法来启动其他程序

也就是说,
在编写Java程序时,有时候我们需要调用其他的诸如 exe,bat ,shell  这样的程序或脚本。在Java中提供了两种方法来启动其他程序:
(1) 使用Runtime的exec()方法
(2) 使用ProcessBuilder的start()方法

■代码

・Runtime

String command = "/XXXX/XXX/xxx.bat param1";
Process pro1 = Runtime.getRuntime().exec(command);
InputStream errorInfo = pro1.getErrorStream();

====

・ProcessBuilder

List<String> commandList = new ArrayList<>();
commandList.add("/XXXX/XXX/xxx.bat");
commandList.add("param1");
ProcessBuilder pb = new ProcessBuilder(commandList);
Process pro2 = pb.start();
pro2.waitFor();

===

■类的方法

・Process.waitFor()方法

processBuilder.start() 会立刻返回,不会待ps进程结束。所以Process提供waitFor方法,调用后线程阻塞,直到ps命令结束。
 

・Process.getErrorStream()方法

创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin,stdout,stderr)操作都将通过三个流 (getOutputStream(),getInputStream(),getErrorStream()) 重定向到父进程。
 

・Process.redirectErrorStream(true)方法:

合并输出流和错误流。

Process阻塞问题_Dancen的博客-CSDN博客_process start 阻塞

public int execute()
{
	int rs = 0;
	String[] cmds = {...};//command and arg  
	ProcessBuilder builder = new ProcessBuilder(cmds);  
	builder.redirectErrorStream(true);  
	Process process = builder.start();  
	BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));  
	String output = null;  
	while (null != (readLine = br.readLine()))
	{  
   		print(output);   
	}  
	rs = process.waitFor();
	return rs;
} 

==

■可运行代码

・java代码   (直接运行)

package com.sxz.study.process;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class TestProcess {

	public static void main(String[] args) {

		List<String> commandList = new ArrayList<>();
		commandList.add("C:\\myBat\\CreateFile.bat");
		commandList.add("test0001");
		commandList.add("the test 0002 row");
		commandList.add("theTest0003Row");
		ProcessBuilder pb = new ProcessBuilder(commandList);
		Process pro2 = null;
		try {
			pro2 = pb.start();
			// =====CreateFile.bat=================================START			
//			@echo off
//			 
//			set param1=%1
//			set param2=%2
//			set param3=%3
//			 
//			cd %~dp0
//
//			echo %param1%>testProcess.txt
//			echo %param2%>>testProcess.txt
//			echo %param3%>>testProcess.txt		
			// =====CreateFile.bat=================================END
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			pro2.waitFor();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}


	}

}

・运行的bat代码

@echo off
 
set param1=%1
set param2=%2
set param3=%3
 
cd %~dp0

echo %param1%>testProcess.txt
echo %param2%>>testProcess.txt
echo %param3%>>testProcess.txt

・结果

 ====

test0001
"the test 0002 row"
theTest0003Row

・java代码   (运行,并获取运行的程序 的 输出)

获取输出核心代码

		List<String> commandList = new ArrayList<>();
		commandList.add("C:\\myBat\\CreateFile.bat");
。。。
		ProcessBuilder pb = new ProcessBuilder(commandList);
		Process pro2 = null;
。。。。
		try {
			pro2 = pb.start();

			InputStreamReader ir = new InputStreamReader(pro2.getInputStream());
			LineNumberReader ls = new LineNumberReader(ir);
			String line = "";
			while ((line = ls.readLine()) != null) {
				System.out.println("---" + line);
			}
。。。

===全部代码===

package com.sxz.study.process;
 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;
 
public class TestProcess {
 
	public static void main(String[] args) {
 
		List<String> commandList = new ArrayList<>();
		commandList.add("C:\\myBat\\CreateFile.bat");
		commandList.add("test0001");
		commandList.add("the test 0002 row");
		commandList.add("theTest0003Row");
		ProcessBuilder pb = new ProcessBuilder(commandList);
		Process pro2 = null;
		try {
			pro2 = pb.start();
			// =====CreateFile.bat=================================START			
//			@echo off
//			chcp 65001 
//
//			set param1=%1
//			set param2=%2
//			set param3=%3
//
//			echo "Begin..."
//			 
//			cd %~dp0
//
//			echo %param1%>testProcess.txt
//			echo %param2%>>testProcess.txt
//			echo %param3%>>testProcess.txt
//
//			dir
//
//			echo "End..."
			// =====CreateFile.bat=================================END
			
			InputStreamReader ir = new InputStreamReader(pro2.getInputStream());
			LineNumberReader ls = new LineNumberReader(ir);
			String line = "";
			while ((line = ls.readLine()) != null) {
				System.out.println("---" + line);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			pro2.waitFor();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
 
 
	}
 
}

・对应的bat代码 (有输出)

@echo off
chcp 65001 

set param1=%1
set param2=%2
set param3=%3

echo "Begin..."
 
cd %~dp0

echo %param1%>testProcess.txt
echo %param2%>>testProcess.txt
echo %param3%>>testProcess.txt

dir

echo "End..."

・运行结果(可以获得输出)

 === 

 ===

■Java Process.exitValue & Process.waitFor()

都可以获得返回值,推荐使用  Process.waitFor()

Process.exitValue() 采用非阻塞的方式返回,如果没有立即拿到返回值,则抛出异常

Process.waitFor() 当前线程等待,如有必要,一直要等到由该 Process 对象表示的进程已经终止。但是如果我们在调用此方法时,如果不注意的话,很容易出现主线程阻塞,Process也挂起的情况。在调用waitFor() 的时候,Process需要向主线程汇报运行状况,所以要注意清空缓存区,即InputStream和ErrorStream,在网上,很多只提到处理 InputStream,忽略了ErrorStream。以下一段代码,贴出来,仅做参考。

======

以下面的代码为例

package com.sxz.study.process;
 
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;
 
public class TestProcess {
 
	public static void main(String[] args) {
 
		List<String> commandList = new ArrayList<>();
		commandList.add("C:\\myBat\\CreateFile.bat");
		commandList.add("test0001");
		commandList.add("the test 0002 row");
		commandList.add("theTest0003Row");
		ProcessBuilder pb = new ProcessBuilder(commandList);
		Process pro2 = null;
		try {
			pro2 = pb.start();
			// =====CreateFile.bat=================================START			
//			chcp 65001
//			@echo off
//			 
//			set param1=%1
//			set param2=%2
//			set param3=%3
//			 
//			cd %~dp0
//			echo "Test out put"
//			 
//			echo %param1%>testProcess.txt
//			echo %param2%>>testProcess.txt
//			echo %param3%>>testProcess.txt
//
//			ping localhost	
			// =====CreateFile.bat=================================END
					
			InputStreamReader ir = new InputStreamReader(pro2.getInputStream());
			LineNumberReader ls = new LineNumberReader(ir);
			String line ="";
			while((line = ls.readLine())!=null){
				System.out.println("----:"+line);
			}
			
			int result1 = pro2.exitValue();
			System.out.println("result1----"+result1);
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		try {
			int result2 = pro2.waitFor();
			System.out.println("result2----"+result2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
 
 
	}
 
}

正常运行的结果

----:
----:C:\myProject\20230321\MyJava001\MyJava001>chcp 65001 
----:Active code page: 65001
----:"Test out put"
----:
----:Pinging DLC5CG1464WW9L.dir.svc.accenture.com [::1] with 32 bytes of data:
----:Reply from ::1: time<1ms 
----:Reply from ::1: time<1ms 
----:Reply from ::1: time<1ms 
----:Reply from ::1: time<1ms 
----:
----:Ping statistics for ::1:
----:    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
----:Approximate round trip times in milli-seconds:
----:    Minimum = 0ms, Maximum = 0ms, Average = 0ms
result1----0
result2----0

如果去掉40-45行,则会报错

Exception in thread "main" java.lang.IllegalThreadStateException: process has not exited
    at java.lang.ProcessImpl.exitValue(ProcessImpl.java:510)
    at com.sxz.study.process.TestProcess.main(TestProcess.java:47)

■其它资料整理

https://blog.csdn.net/sxzlc/article/details/128607097

■参考

ProcessBuilder 、Runtime和Process 的区别_sunshine_pb的博客-CSDN博客_processbuilder和runtime的区

====

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值