Himself12794 Himself12794 - 4 months ago 14
Perl Question

Send ByteArrayOutputStream to Perl script, then read response

I have a ByteArrayOuputStream I received from performing a diff. Java's parsing of this is too slow, so I decided to try to pass the parsing off to a Perl script. I'm having a little trouble getting the script to receive data from this output stream. When I run my code, the application hangs indefinitely. This is what I have so far:

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);
}


And here is my Perl script:

#!/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")


Is there a way to actually do what I am trying to do?

Edit: This is how I was doing it in 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;
}


Edit 2
If you want some context, you can refer to this Related question

Answer

I'm using a tablet at present so I can't help much, but your Perl needs some work.

You shouldn't use for $line ( <> ) as that will try to read all of the input into a list before starting to iterate. You also don't use $line so you should read straight into $_ with

while ( <> ) { ... }

There's also no need to chomp every line, and I dont understand why do you call print for every record? It's after the chomp so the output will be a copy of the input all on one very long line with the aggregate values at the very end.

I suspect the Perl script is receiving the data just fine, but having trouble fitting all of the input into memory at once together with a second copy of everything as output!