处理来自 apache-commons exec 的输出 [英] Process output from apache-commons exec

查看:28
本文介绍了处理来自 apache-commons exec 的输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里不知所措.我确信这很简单,而且我对 java 和流的理解很可能有很大的漏洞.我认为有太多的类让我有点不知所措,试图通过 API 找出我想要何时以及如何使用大量输入/输出流.

I am at my wits end here. I'm sure this is something simple and I most likely have huge holes in my understanding of java and streams. I think there are so many classes that I'm a bit overwhelmed with trying to poke through the API to figure out when and how I want to use the multitude of input/output streams.

我刚刚了解到 apache 公共库的存在(自学 java 失败),目前我正在尝试将我的一些 Runtime.getRuntime().exec 转换为使用公共 - exec.它已经修复了一些每 6 个月一次这个问题突然出现然后消失的 exec 风格问题.

I just learned about the existence of the apache commons library (self teaching java fail), and am currently trying to convert some of my Runtime.getRuntime().exec to use the commons - exec. Already it's fixed some of the once every 6 months this problem crops up then goes away style problems with exec.

代码执行 perl 脚本,并在运行时在 GUI 中显示脚本的标准输出.

The code executes a perl script, and displays the stdout from the script in the GUI as it is running.

调用代码在 Swingworker 中.

The calling code is inside of a swingworker.

我迷失了如何使用 pumpStreamHandler...无论如何这里是旧代码:

I'm getting lost how to use the pumpStreamHandler... anyway here is the old code:

String pl_cmd = "perl script.pl"
Process p_pl = Runtime.getRuntime().exec( pl_cmd );

BufferedReader br_pl = new BufferedReader( new InputStreamReader( p_pl.getInputStream() ) );

stdout = br_pl.readLine();
while ( stdout != null )
{
    output.displayln( stdout );
    stdout = br_pl.readLine();
}

我想这就是我很久以前不完全理解的复制粘贴代码所得到的.上面我假设正在执行该过程,然后获取输出流(通过getInputStream"?),将其放入缓冲阅读器中,然后将在那里循环直到缓冲区为空.

I guess this is what I get for copy pasting code I don't fully understand a long time ago. The above I assume is executing the process, then grabs the outputstream (via "getInputStream"?), places it into a buffered reader, then will just loop there until the buffer is empty.

我不明白的是为什么这里不需要等待"样式的命令?是否有可能在一段时间内缓冲区为空,退出循环并在进程仍在进行时继续?当我运行它时,情况似乎并非如此.

What I don't get is why there is no need for a 'waitfor' style command here? Isn't it possible that there will be some time in which the buffer will be empty, exit the loop, and continue on while the process is still going? When I run it, this doesn't seem to be the case.

无论如何,我正在尝试使用 commons exec 获得相同的行为,基本上再次来自谷歌找到的代码:

In any event, I'm trying to get the same behavior using commons exec, basically again going from google found code:

DefaultExecuteResultHandler rh = new DefaultExecuteResultHandler();
ExecuteWatchdog wd  = new ExecuteWatchdog( ExecuteWatchdog.INFINITE_TIMEOUT );
Executor exec = new DefaultExecutor();

ByteArrayOutputStream out = new ByteArrayOutputStream();
PumpStreamHandler psh = new PumpStreamHandler( out );

exec.setStreamHandler( psh );
exec.setWatchdog( wd );

exec.execute(cmd, rh );
rh.waitFor();

我想弄清楚 pumpstreamhandler 在做什么.我假设这将获取 exec 对象的输出,并填充我提供给它的来自 perl 脚本的 stdout/err 的字节的 OutputStream?

I'm trying to figure out what pumpstreamhandler is doing. I assume that this will take the output from the exec object, and fill the OutputStream I provide it with the bytes from the perl script's stdout/err?

如果是这样,您将如何获得上述行为以使其逐行流式传输输出?在示例中,人们显示您在最后调用 out.toString(),我认为这只会在脚本运行完成后转储脚本的所有输出?您将如何做到这一点,以便它在逐行运行时显示输出?

If so how would you get the above behavior to have it stream the output line by line? In examples people show you call the out.toString() at the end, and I assume this would just give me a dump of all the output from the script once it is done running? How would you do it such that it would show the output as it is running line by line?

------------未来编辑 ---------------------

------------Future Edit ---------------------

通过谷歌找到这个并且效果很好:

Found this via google and works nice as well:

public static void main(String a[]) throws Exception
{
    ByteArrayOutputStream stdout = new ByteArrayOutputStream();
    PumpStreamHandler psh = new PumpStreamHandler(stdout);
    CommandLine cl = CommandLine.parse("ls -al");
    DefaultExecutor exec = new DefaultExecutor();
    exec.setStreamHandler(psh);
    exec.execute(cl);
    System.out.println(stdout.toString());
}

推荐答案

不要将 ByteArrayOutputStream 传递给 PumpStreamHandler,使用抽象类 的实现>org.apache.commons.exec.LogOutputStream.来自 javadoc:

Don't pass a ByteArrayOutputStream to the PumpStreamHandler, use an implementation of the abstract class org.apache.commons.exec.LogOutputStream. From the javadoc:

该实现解析传入的数据以构造一行并将完整的行传递给用户定义的实现.

The implementation parses the incoming data to construct a line and passes the complete line to an user-defined implementation.

因此 LogOutputStram 正在预处理输出,让您可以控制处理单个行而不是原始字节.像这样:

Thus the LogOutputStram is preprocessing the output to give you the control of handling individual lines instead of the raw bytes. Something like this:

import java.util.LinkedList;
import java.util.List;
import org.apache.commons.exec.LogOutputStream;

public class CollectingLogOutputStream extends LogOutputStream {
    private final List<String> lines = new LinkedList<String>();
    @Override protected void processLine(String line, int level) {
        lines.add(line);
    }   
    public List<String> getLines() {
        return lines;
    }
}

然后在对 exec.execute 的阻塞调用之后,您的 getLines() 将具有您正在寻找的标准输出和标准错误.ExecutionResultHandler 从只是执行过程的角度来看是可选的,并将所有 stdOut/stdErr 收集到一个行列表中.

Then after the blocking call to exec.execute your getLines() will have the standard out and standard error you are looking for. The ExecutionResultHandler is optional from the perspective of just executing the process, and collecting all the stdOut/stdErr into a list of lines.

这篇关于处理来自 apache-commons exec 的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆