我需要将一个字符串通过Java程序运行,并获取输出。Java程序通过标准输入接受字符串。以下是有效的代码:
my $output = `echo $string | java -jar java_program.jar`;
有一个问题: $string
可能是任何东西。对于这个问题,您有什么好的解决方案吗?
open PIPE, "| java -jar java_program.jar";
print PIPE "$string";
close(PIPE);
看起来你实际上需要命令的输出。你可以使用IPC::Open2打开两个管道(一个用于进程输入,一个用于输出),但这样做会冒着同时处理两个管道而导致死锁的风险。
你可以通过让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);
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文档以获取更多创建临时文件的更干净的方法。我建议您查看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
与其他模块的比较。
创建一个与您的Shell类似的流水线。
这是我们可怕的字符串:
my $str = "foo * ~ bar \0 baz *";
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";
}
}
open
操作符中特殊的"-|"
参数。
如果你在命令
'-'
上打开一个管道,即使用open()
的2个参数(或1个参数)形式的'|-'
或'-|'
,则会隐式地进行fork
,并且open
的返回值是父进程中子进程的pid,而在子进程中是0
...文件句柄对于父进程表现正常,但对于该文件句柄的i/o从/到子进程的STDOUT
/STDIN
进行传输。
unpack
用于查看从管道读取的数据内容。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";
}
$|
设置为真值会刷新当前选定的文件句柄并将其置于无缓冲模式。 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字符得以保留。
你是否研究过IPC::Run
?这可能是你正在寻找的语法:
use IPC::Run qw( run );
my $input = $string;
my ($out, $err);
run ["java -jar java_program.jar"], \$input, \$out, \$err;
内置的IPC::Open2模块提供了一个函数来处理双向管道,而无需外部文件。
select
操作。如果你不在Windows上,或者阻塞是可以接受的,那么open2或open3可能适合你。 - daotoad