我需要通过Java程序运行一个字符串,然后检索输出。 Java程序通过标准输入来接受字符串。以下作品:如何将输入从Perl中输入到Java命令中?
my $output = `echo $string | java -jar java_program.jar`;
有一个问题:$string
可能是几乎任何东西。有什么想法解决这个问题的好办法?
我需要通过Java程序运行一个字符串,然后检索输出。 Java程序通过标准输入来接受字符串。以下作品:如何将输入从Perl中输入到Java命令中?
my $output = `echo $string | java -jar java_program.jar`;
有一个问题:$string
可能是几乎任何东西。有什么想法解决这个问题的好办法?
,我建议你看看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。
如果您可以使用CPAN模块(并且我假设大多数人可以),请使用IPC::Run3查看Ivan's answer。它应该处理你需要的一切。
如果你不能使用模块,下面是如何做简单的香草方式的事情。
您可以使用管道做你的输入,这将避免所有这些命令行引述问题:
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);
的另一种选择是周围做事情的其他方式。把$字符串中的临时文件,然后用它作为输入到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,了解各种更干净的方法,以更干净地创建临时文件。
内置的IPC :: Open2模块提供了一种处理双向管道而无需外部文件的功能。
你看过IPC::Run
?
语法类似于这可能是你在找什么:
use IPC::Run qw(run);
my $input = $string;
my ($out, $err);
run ["java -jar java_program.jar"], \$input, \$out, \$err;
创建一个管道,就像你的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
是子进程内的子进程的子进程号,子进程内的子进程号为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生存的旅程。
这看起来不错,但我如何得到命令的输出? – spudly
@spudly,你不能与该建议。你需要使用open2(),检查perldoc perlipc是否为“双向通信” – jsoverson
在Windows系统上,open2或open3的许多用法都因为你只能在Win32上选择一个套接字而受到严重阻碍。如果你不在Windows上或者阻塞没有问题,那么open2或open3可能会为你解决问题。 – daotoad