Java 如何捕获从批处理执行的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

我有一个批处理文件,需要从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方法会返回我想要处理的数据。

您可以控制脚本吗?我会尝试将可执行文件中的返回值(这就是您想要的?)存储到环境变量中。你可能得把它出口出去。这里有一个关于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您无法访问外部程序对环境所做的修改。你确定这样行吗?你试过了吗。好吧,你只能为要执行的程序设置一个修改过的环境,而不能反过来做什么