将ByteArrayOutputStream发送到Perl脚本,然后读取响应

时间:2016-07-28 23:27:34

标签: java perl stream outputstream

我有一个我从执行差异收到的ByteArrayOuputStream。 Java对此的解析太慢了,所以我决定尝试将解析传递给Perl脚本。我在让脚本从此输出流中接收数据时遇到一些麻烦。当我运行我的代码时,应用程序无限期挂起。这就是我到目前为止所做的:

public static Diff analyzeDiff(ByteArrayOutputStream baos) throws IOException {

    ProcessBuilder pb = new ProcessBuilder();
    pb.command("perl/path/perl", TEMP.getAbsolutePath());
    Process process = pb.start();
    OutputStream str = process.getOutputStream();
    baos.writeTo(str);
    str.flush();
    try {
        process.waitFor();
    } catch (InterruptedException e) {
        BufferedReader bf = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        while ((line = bf.readLine()) != null) {
            System.out.println(line);
        }
    }

    return null;
}

@Test
public void testDiffParser() throws IOException {
    DiffParser.init();

    File test = new File("path/to/file/test.diff");

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    baos.write(FileUtils.readFileToByteArray(test));
    //String output = baos.toString();
    //System.out.println(output);

    DiffParser.analyzeDiff(baos);
    //DiffParser.analyzeDiff(output);
}

这是我的Perl脚本:

#!/usr/bin/perl
use strict;
use warnings;

my $additions = 0;
my $deletions = 0;
my $filesChanged = 0;

my $fileAdded = 0;
my $line;

foreach $line ( <> ) {
    $_ = $line;
    chomp( $_ );
    print( $_ );
    if ( /^\-\-\-/m ) {
        $fileAdded = 1;
    } elsif ( /^\+\+\+/m && $fileAdded ) {
        $filesChanged++;
        $fileAdded = 0;
    } elsif ( /^\+/ ) {
        $additions++;
        $fileAdded = 0;
    } elsif ( /^\-/ ) {
        $deletions++;
        $fileAdded = 0;
    } else {
        $fileAdded = 0;
    }
}

print("$additions $deletions $filesChanged\n")

有没有办法真正做我想做的事情?

编辑:这就是我在Java中的表现:

private Diff parseDiff(final ByteArrayOutputStream baos) {

    final Diff diff = new Diff();

    int filesChanged = 0;
    int additions = 0;
    int deletions = 0;

    boolean fileAdded = false;

    final String[] lines = baos.toString().split("\n");

    for (final String line : lines) {

        if (line.startsWith("---")) {
            fileAdded = true;
        } else if (line.startsWith("+++") && fileAdded) {
            filesChanged++;
            fileAdded = false;
        } else if (line.startsWith("+")) {
            additions++;
            fileAdded = false;
        } else if (line.startsWith("-")) {
            deletions++;
            fileAdded = false;
        } else {
            fileAdded = false;
        }

    }

    diff.additions = additions;
    diff.deletions = deletions;
    diff.changedFiles = filesChanged;

    return diff;
}

编辑2 如果您需要某些上下文,可以参考此Related question

2 个答案:

答案 0 :(得分:1)

我目前正在使用平板电脑,所以我无法提供太多帮助,但您的Perl需要一些工作。

您不应该使用for $line ( <> ),因为在开始迭代之前,它会尝试将输入的所有读入列表。您也不能使用$line,因此您应该直接阅读$_

while ( <> ) { ... }

也没有必要chomp每一行,我不明白为什么你为每条记录打电话给print?它位于chomp之后,因此输出将是一个非常长的行上的输入的副本,最后的聚合值。

我怀疑Perl脚本接收的数据很好,但是无法将所有输入同时输入到内存中,还有第二个副本作为输出!

答案 1 :(得分:0)

使用ByteArrayOutputStream意味着diff的整个结果需要一次性存储在内存中,而不是以块的形式进行处理和垃圾收集。由于内存不足以及始终执行垃圾收集,您的Java程序可能会很慢。

与Perl相比,Java在任何任务上都会快得多。它是一种即时编译语言,而不是Perl中的解释语言。参见例如http://blog.carlesmateo.com/2014/10/13/performance-of-several-languages/https://attractivechaos.github.io/plb/https://en.wikipedia.org/wiki/Java_performance(与其他语言比较)。

如果您需要性能,则应优化Java代码,而不是创建对Perl的依赖。