Java 如何捕获从批处理执行的EXE返回的数据?
我有一个批处理文件,需要从java程序调用。批处理文件依次调用EXE。EXE程序将返回我要处理的数据。如果EXE将数据打印到控制台,我可以按如下方式捕获数据。但是当EXE在完成后返回数据时,我无法捕获它Java 如何捕获从批处理执行的EXE返回的数据?,java,process,batch-file,Java,Process,Batch File,我有一个批处理文件,需要从java程序调用。批处理文件依次调用EXE。EXE程序将返回我要处理的数据。如果EXE将数据打印到控制台,我可以按如下方式捕获数据。但是当EXE在完成后返回数据时,我无法捕获它 ProcessBuilder pb = new ProcessBuilder("foo.bat"); Process p = pb.start(); int exitValue = p.waitFor(); BufferedReader reader; // System.out.printl
ProcessBuilder pb = new ProcessBuilder("foo.bat");
Process p = pb.start();
int exitValue = p.waitFor();
BufferedReader reader;
// System.out.println("Exit Value" + exitValue);
if (exitValue == 0) {
reader = new BufferedReader(new InputStreamReader(p
.getInputStream()));
} else {
reader = new BufferedReader(new InputStreamReader(p
.getErrorStream()));
}
StringBuffer sb = new StringBuffer();
String temp = reader.readLine();
while (temp != null) {
sb.append(temp);
temp = reader.readLine();
}
reader.close();
System.out.println(sb.toString());
我需要如何捕获从批处理文件执行的EXE返回的数据
EXE基本上是一个C程序。当我调用C程序时,main方法会返回我想要处理的数据。您可以控制脚本吗?我会尝试将可执行文件中的返回值(这就是您想要的?)存储到环境变量中。你可能得把它出口出去。这里有一个关于Java变量的教程 多亏了jitters的评论-不,它不起作用。我们不能以“全局”方式更改环境变量的值(现在我知道了…)
但是,这个想法需要一些调整:我仍然会尝试将返回值存储在一个全局可访问的资源中:只需将返回值发送到一个文件(
exec myapp>result.txt
)并在java应用程序中读取该文件中的值。我想我不久前也遇到了同样的问题。前面策略的一个问题是,您正在等待流程完成(waitFor)以捕获从中返回的数据。如果过程失败或挂断,您可能会遇到问题。更好的方法是这样:
您应该创建两个线程来使用进程的输入流和错误流,独立于waitFor调用。像这样的东西应该有用:
1.-创建一个封装流程执行的类:
public class ExecutionWrapper {
private int exitStatus;
private String[] command;
private String[] environment;
private String directory;
private boolean running;
private Process process;
private ExecutionWrapperOutput error;
private ExecutionWrapperOutput output;
public ExecutionWrapper(String command, String[] environment, String directory) {
this.command = new String[] { command };
this.environment = environment;
this.directory = directory;
this.exitStatus = -1;
}
public ExecutionWrapper(List<String> command, List<String> environment, String directory) {
if (command != null)
this.command = command.toArray(new String[command.size()]);
if (environment != null)
this.environment = environment.toArray(new String[environment.size()]);
this.directory = directory;
this.exitStatus = -1;
}
public void start() {
try {
this.process = Runtime.getRuntime().exec(this.command, this.environment, new File(this.directory));
this.running = true;
// Error and information messages
this.error = new ExecutionWrapperOutput(this.process.getErrorStream());
this.output = new ExecutionWrapperOutput(this.process.getInputStream());
// Start the messaging threads
this.error.start();
this.output.start();
// Final status
Runnable runner = new Runnable() {
public void run() {
try {
ExecutionWrapper.this.exitStatus = ExecutionWrapper.this.process.waitFor();
ExecutionWrapper.this.running = false;
ExecutionWrapper.this.process.destroy();
} catch (Exception ex) {
LoggingUtiles.exception(ex);
ExecutionWrapper.this.exitStatus = -1;
}
}
};
new Thread(runner).start();
} catch (Throwable t) {
LoggingUtiles.exception(t);
}
}
public void stop() {
this.running = false;
this.process.destroy();
}
public boolean isRunning() {
return running;
}
public int getExitStatus() {
return exitStatus;
}
public String[] getError(boolean clear) {
return this.error.getLines(clear);
}
public String[] getOutput(boolean clear) {
return this.output.getLines(clear);
}
public String[] getCommand() {
return command;
}
public String getDirectory() {
return directory;
}
public void waitFor() {
try {
process.waitFor();
} catch (Throwable t) {
LoggingUtiles.exception(t);
}
}
}
公共类ExecutionWrapper{
私有内部存在状态;
私有字符串[]命令;
私有字符串[]环境;
私有字符串目录;
私有布尔运行;
私有过程;
私有ExecutionWrapperOutput错误;
私有ExecutionWrapperOutput;
public ExecutionWrapper(字符串命令、字符串[]环境、字符串目录){
this.command=新字符串[]{command};
这个。环境=环境;
this.directory=目录;
this.exitStatus=-1;
}
公共ExecutionWrapper(列表命令、列表环境、字符串目录){
if(命令!=null)
this.command=command.toArray(新字符串[command.size()]);
if(环境!=null)
this.environment=environment.toArray(新字符串[environment.size()]);
this.directory=目录;
this.exitStatus=-1;
}
公开作废开始(){
试一试{
this.process=Runtime.getRuntime().exec(this.command,this.environment,新文件(this.directory));
这是真的;
//错误和信息消息
this.error=新的ExecutionWrapperOutput(this.process.getErrorStream());
this.output=新的ExecutionWrapperOutput(this.process.getInputStream());
//启动消息传递线程
这是.error.start();
this.output.start();
//最终状态
Runnable runner=新的Runnable(){
公开募捐{
试一试{
ExecutionWrapper.this.exitStatus=ExecutionWrapper.this.process.waitFor();
ExecutionWrapper.this.running=false;
ExecutionWrapper.this.process.destroy();
}捕获(例外情况除外){
LoggingUtiles.例外(ex);
ExecutionWrapper.this.exitStatus=-1;
}
}
};
新线程(runner.start();
}捕获(可丢弃的t){
记录异常(t);
}
}
公共停车场(){
this.running=false;
this.process.destroy();
}
公共布尔值正在运行(){
返回运行;
}
public int getExitStatus(){
返回现有状态;
}
公共字符串[]getError(布尔清除){
返回此.error.getLines(清除);
}
公共字符串[]getOutput(布尔清除){
返回此.output.getLines(清除);
}
公共字符串[]getCommand(){
返回命令;
}
公共字符串getDirectory(){
返回目录;
}
公共空间等待(){
试一试{
process.waitFor();
}捕获(可丢弃的t){
记录异常(t);
}
}
}
2.-然后,创建ExecutionWrapperOutput类,该类处理流程流的输出:
public class ExecutionWrapperOutput extends Thread {
private InputStream is;
private List<String> output;
private Object mutex = new Object();
ExecutionWrapperOutput(InputStream is) {
this.is = is;
this.output = new ArrayList<String>();
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
synchronized (mutex) {
output.add(line);
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
public String[] getLines(boolean clear) {
String[] lines = null;
synchronized (mutex) {
lines = output.toArray(new String[] {});
if (clear)
output.clear();
}
return lines;
}
}
公共类ExecutionWrapperOutput扩展线程{
私有输入流是;
私有列表输出;
私有对象互斥=新对象();
ExecutionWrapperOutput(InputStream为){
this.is=is;
this.output=new ArrayList();
}
公开募捐{
试一试{
InputStreamReader isr=新的InputStreamReader(is);
BufferedReader br=新的BufferedReader(isr);
字符串行=null;
而((line=br.readLine())!=null){
已同步(互斥){
输出。添加(行);
}
}
}捕获(ioe异常ioe){
ioe.printStackTrace();
}
}
公共字符串[]获取行(布尔清除){
字符串[]行=null;
已同步(互斥){
lines=output.toArray(新字符串[]{});
如果(清除)
output.clear();
}
回流线;
}
}
也许这一切都对你有用。现在让我看看它是否有效…AFAIK您无法访问外部程序对环境所做的修改。你确定这样行吗?你试过了吗。好吧,你只能为要执行的程序设置一个修改过的环境,而不能反过来做什么