我需要通过Java程序运行一个字符串,然后检索输出。 Java程序通过标准输入接受字符串。以下作品:
my $output = `echo $string | java -jar java_program.jar`;
有一个问题:$string
几乎可以解决任何问题。有关解决这个问题的任何想法吗?
答案 0 :(得分:6)
如果您可以使用CPAN模块(我假设大多数人都可以),请使用Ivan's answer查看IPC::Run3。它应该处理你需要的一切。
如果你不能使用模块,这里是如何以普通的方式做事。
您可以使用管道进行输入,它将避免所有这些命令行引用问题:
open PIPE, "| java -jar java_program.jar";
print PIPE "$string";
close(PIPE);
看起来你实际上需要输出命令。你可以打开两个管道,例如IPC::Open2(来自java进程),但你可能会陷入僵局,试图同时处理两个管道。
您可以通过将java输出到文件,然后从该文件中读取来避免这种情况:
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);
另一种选择是以相反的方式做事。将$ string放在一个临时文件中,然后将其用作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);
请注意,这不是执行临时文件的最佳方式;为简单起见,我刚刚使用了output.txt
和input.txt
。查看File::Temp docs以获得更清晰地创建临时文件的各种更简洁的方法。
答案 1 :(得分:6)
我建议您查看IPC::Run3
模块。它使用非常简单的界面,允许获得STDERR
和STDOUT
。这是一个小例子:
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";
请参阅IPC::Run3
comparation with other modules。
答案 2 :(得分:2)
你有没有看过IPC::Run
?
您可能正在寻找与此类似的语法:
use IPC::Run qw( run );
my $input = $string;
my ($out, $err);
run ["java -jar java_program.jar"], \$input, \$out, \$err;
答案 3 :(得分:2)
像你的shell一样创建一个管道。
这是我们可怕的字符串:
my $str = "foo * ~ bar \0 baz *";
我们将向后构建管道,因此首先我们从Java程序中收集输出:
my $pid1 = open my $fh1, "-|";
die "$0: fork: $!" unless defined $pid1;
if ($pid1) {
# grab output from Java program
while (<$fh1>) {
chomp;
my @c = unpack "C*" => $_;
print "$_\n => @c\n";
}
}
请注意Perl的open
运算符的特殊"-|"
参数。
如果您在命令
'-'
,即上打开管道,则'|-'
或'-|'
具有2个参数(或1个参数)形式open()
,然后有一个隐式fork
完成,open
的返回值是父进程中子进程的pid,以及子进程中的0
...文件句柄对于父文件正常运行,但该文件句柄的i / o通过管道传送到子进程的STDOUT
/STDIN
。
unpack
用于查看从管道读取的数据的内容。
在你的程序中,你需要运行Java程序,但下面的代码使用了合理的传真:
else {
my $pid2 = open my $fh2, "-|";
die "$0: fork: $!" unless defined $pid2;
if ($pid2) {
$| = 1;
open STDIN, "<&=" . fileno($fh2)
or die "$0: dup: $!";
# exec "java", "-jar", "java_program.jar";
# simulate Java program
exec "perl", "-pe", q(
BEGIN { $" = "][" }
my @a = split " ", scalar reverse $_;
$_ = "[@a]\n";
);
die "$0: exec failed";
}
最后,这个不起眼的孙子只是打印出可怕的字符串(它来自Java程序的标准输入)并退出。将$|
设置为true值会刷新当前选定的文件句柄并将其置于无缓冲模式。
else {
print $str;
$| = 1;
exit 0;
}
}
其输出:
$ ./try [*][zab][][rab][~][*][oof] => 91 42 93 91 122 97 98 93 91 0 93 91 114 97 98 93 91 126 93 91 42 93 91 111 111 102 93
请注意,NUL在旅行中幸存下来。
答案 4 :(得分:1)
内置的IPC :: Open2模块提供了一个无需外部文件即可处理双向管道的功能。