Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I pipe input into a Java command from Perl?

Tags:

command

pipe

perl

I need to run a string through a Java program and then retrieve the output. The Java program accepts the string through standard input. The following works:

my $output = `echo $string | java -jar java_program.jar`;

There is one problem: $string could be just about anything. Any thoughts on a good solution to this problem?

like image 286
Stephen Sorensen Avatar asked Dec 15 '09 18:12

Stephen Sorensen


2 Answers

I suggest you to look at IPC::Run3 module. It uses very simple interface and allow to get STDERR and STDOUT. Here is small example:

use IPC::Run3;
## store command output here
my ($cmd_out, $cmd_err);
my $cmd_input = "put your input string here";
run3([ 'java', '-jar', 'java_program.jar'], \$cmd_input, \$cmd_out, \$cmd_err);
print "command output [$cmd_out] error [$cmd_err]\n";

See IPC::Run3 comparation with other modules.

like image 137
Ivan Nevostruev Avatar answered Oct 09 '22 09:10

Ivan Nevostruev


If you can use CPAN modules (and I'm assuming most people can), look at Ivan's answer on using IPC::Run3. It should handle everything you need.

If you can't use modules, here's how to do things the plain vanilla way.

You can use a pipe to do your input, and it will avoid all those command line quoting issues:

open PIPE, "| java -jar java_program.jar";
print PIPE "$string";
close(PIPE);

It looks like you actually need the output of the command, though. You could open two pipes with something like IPC::Open2 (to and from the java process) but you risk putting yourself in deadlock trying to deal with both pipes at the same time.

You can avoid that by having java output to a file, then reading from that file:

open PIPE, "| java -jar java_program.jar > output.txt";
print PIPE "$string";
close(PIPE);

open OUTPUT, "output.txt";
while (my $line = <OUTPUT>) {
    # do something with $line
}
close(OUTPUT);

The other option is to do things the other way around. Put $string in a temporary file, then use it as input to java:

open INPUT, "input.txt";
print INPUT "$string";
close(INPUT); 

open OUTPUT, "java -jar java_program.jar < input.txt |";
while (my $line = <OUTPUT>) {
    # do something with the output
}
close(OUTPUT);

Note that this isn't the greatest way to do temporary files; I've just used output.txt and input.txt for simplicity. Look at the File::Temp docs for various cleaner ways to create temporary files more cleanly.

like image 28
Todd Gamblin Avatar answered Oct 09 '22 10:10

Todd Gamblin