如何从 Perl 将输入传送到 Java 命令?

发布于 2024-08-15 18:02:31 字数 207 浏览 2 评论 0 原文

我需要通过 Java 程序运行一个字符串,然后检索输出。 Java 程序通过标准输入接受字符串。以下内容有效:

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

有一个问题:$string 可以是任何东西。对于解决这个问题有什么好的想法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧街凉风 2024-08-22 18:02:31

我建议您查看 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::Run3 与其他模块的比较

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.

第几種人 2024-08-22 18:02:31

如果您可以使用 CPAN 模块(我假设大多数人都可以),请查看 Ivan 关于使用 的回答 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.txtinput.txt。查看 File::Temp 文档 各种更干净的方法来更干净地创建临时文件。

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.

白日梦 2024-08-22 18:02:31

您是否研究过 IPC::Run

您可能正在寻找与此类似的语法:

use IPC::Run qw( run );
my $input = $string;
my ($out, $err);
run ["java -jar java_program.jar"], \$input, \$out, \$err;

Have you looked into IPC::Run?

Syntax similar to this might be what you are looking for:

use IPC::Run qw( run );
my $input = $string;
my ($out, $err);
run ["java -jar java_program.jar"], \$input, \$out, \$err;
七秒鱼° 2024-08-22 18:02:31

创建一个管道,就像您的 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 的 参数perldoc.perl.org/functions/open.html" rel="nofollow noreferrer">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 在行程中幸存下来。

Create a pipeline just like your shell would.

Here's our scary string:

my $str = "foo * ~ bar \0 baz *";

We'll build our pipeline backwards, so first we gather the output from the Java program:

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";
  }
}

Note the special "-|" argument to Perl's open operator.

If you open a pipe on the command '-' , i.e., either '|-' or '-|' with 2-arguments (or 1-argument) form of open(), then there is an implicit fork done, and the return value of open is the pid of the child within the parent process, and 0 within the child process … The filehandle behaves normally for the parent, but i/o to that filehandle is piped from/to the STDOUT/STDIN of the child process.

The unpack is there to peek into the contents of the data read from the pipe.

In your program, you'll want to run the Java program, but the code below uses a reasonable facsimile:

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";
  }

Finally, the humble grandchild simply prints the scary string (which arrives on the standard input of the Java program) and exits. Setting $| to a true value flushes the currently selected filehandle and puts it in unbuffered mode.

  else {
    print $str;
    $| = 1;
    exit 0;
  }
}

Its output:

$ ./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

Note that the NUL survives the trip.

风透绣罗衣 2024-08-22 18:02:31

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

The builtin IPC::Open2 module provides a function to handle bidirectional-piping without an external file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文