2009-12-15 102 views
6

我需要通过Java程序运行一个字符串,然后检索输出。 Java程序通过标准输入来接受字符串。以下作品:如何将输入从Perl中输入到Java命令中?

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

有一个问题:$string可能是几乎任何东西。有什么想法解决这个问题的好办法?

回答

6

,我建议你看看IPC::Run3模块。它使用非常简单的界面,并允许获得STDERRSTDOUT。下面是小例子:

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::Run3comparation with other modules

6

如果您可以使用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.txtinput.txt。查看File::Temp docs,了解各种更干净的方法,以更干净地创建临时文件。

+0

这看起来不错,但我如何得到命令的输出? – spudly

+1

@spudly,你不能与该建议。你需要使用open2(),检查perldoc perlipc是否为“双向通信” – jsoverson

+0

在Windows系统上,open2或open3的许多用法都因为你只能在Win32上选择一个套接字而受到严重阻碍。如果你不在Windows上或者阻塞没有问题,那么open2或open3可能会为你解决问题。 – daotoad

1

内置的IPC :: Open2模块提供了一种处理双向管道而无需外部文件的功能。

2

你看过IPC::Run

语法类似于这可能是你在找什么:

use IPC::Run qw(run); 
my $input = $string; 
my ($out, $err); 
run ["java -jar java_program.jar"], \$input, \$out, \$err; 
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是子进程内的子进程的子进程号,子进程内的子进程号为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生存的旅程。

相关问题