我有一个需要从java程序调用的批处理文件。批处理文件又调用EXE。 EXE程序将返回我想要处理的数据。如果EXE将数据打印到控制台,则能够按如下方式捕获数据。但是当EXE在完成后返回数据时,我无法捕获它。
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方法返回数据,我想要处理它。
答案 0 :(得分:1)
您是否可以控制脚本? 我会尝试将返回值(这是你想要的吗?)从可执行文件存储到环境变量中。您可能必须将其导出。这是一个关于Java how to handle environment变量的教程。 击>
感谢抖动评论 - 不,它不起作用。我们无法以“全局”方式更改环境变量的值(现在我知道..)
但是,这个想法有点适应:我仍然尝试将返回值存储在全局可访问资源中:只需将返回值发送到文件(exec myapp > result.txt
)并从中读取值你的java应用程序中的文件。
答案 1 :(得分:1)
我想我前段时间遇到了同样的问题。先前策略的一个问题是您正在等待进程完成(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);
}
}
}
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;
}
}
也许这一切对你有用。现在让我,如果它的工作......