【问题标题】:How to give input to java program and continue with execution using PHP?如何为 java 程序提供输入并继续使用 PHP 执行?
【发布时间】:2016-03-26 17:36:50
【问题描述】:

我想使用 php 代码执行 java 程序。当我编写以下代码时,在编辑器中编写的程序正在编译并成功执行。

putenv('path=C:\Program Files\Java\jdk1.8.0_73\bin');

echo shell_exec("javac $output 2>&1"); // for compiling and creating class file

echo exec("java $check 2>&1"); // for executing generated class file and prints output

注意:$output$check 变量包含编译和运行所需的输入

但是,当我尝试执行需要输入一些数据以继续执行的 Java 程序时,上面的代码不起作用。例如,考虑链接中的JavaScannerExamplehttp://alvinalexander.com/java/edu/pj/pj010005

要执行链接中的程序,我想我需要一些交互式控制台来接受输入并继续执行程序。请建议我如何使用 php 实现这一目标?

更新:

@Chris.. 按照建议尝试了proc_open 命令。请参阅下面的代码:

PHP 代码

<?php

$JAVA_HOME = "C:\Java\jdk1.7.0_79";
$PATH = "$JAVA_HOME\bin";
putenv("JAVA_HOME=$JAVA_HOME");
putenv("PATH=$PATH");
$result = shell_exec("javac JavaScannerExample.java 2>&1");
if ($result == ""){
$options = ["bypass_shell" => true];
$proc=proc_open("java JavaScannerExample",
  array(
    array("pipe","r"),
    array("pipe","w"),
    array("pipe","w")
  ),
  $pipes,NULL,NULL,$options);
if (is_resource($proc)) {   
   fwrite($pipes[0], 'Mark');
   fwrite($pipes[0], 32);
   fclose($pipes[0]);
   echo stream_get_contents($pipes[1]); 
   fclose($pipes[1]);
}

}
else{
    echo $result;
}
?>

Java 代码

import java.util.Scanner;

public class JavaScannerExample
{

  public static void main (String[] args)
  {
    // create a scanner so we can read the command-line input
    Scanner scanner = new Scanner(System.in);

    //  prompt for the user's name
    System.out.print("Enter your name: ");

    // get their input as a String
    String username = scanner.next();

    // prompt for their age
    System.out.print("Enter your age: ");

    // get the age as an int
    int age = scanner.nextInt();

    System.out.println(String.format("%s, your age is %d", username, age));

  }

}

PHP 输出

Enter your name: Enter your age:

能否请您检查一下,让我知道我哪里出错了?


更新2:

@Chris.. 感谢您的建议。它帮助我获得了输出。

这里是修改后的php代码:

putenv('path=C:\Program Files\Java\jdk1.8.0_73\bin');
$result = shell_exec("javac JavaScannerExample.java 2>&1");
if ($result == ""){
    $options = ["bypass_shell" => true];
    $proc=proc_open("java JavaScannerExample",
            array(
                    array("pipe","r"),
                    array("pipe","w"),
                    array("pipe","w")
            ),
            $pipes,NULL,NULL,$options);
    if (is_resource($proc)) {
        fwrite($pipes[0], "Mark\n");
        fwrite($pipes[0], "32\n");
        fclose($pipes[0]);
        echo stream_get_contents($pipes[1]);
        fclose($pipes[1]);
    }
}
else{
    echo $result;
}

这是我得到的结果。

Enter your name: Enter your age: Mark, your age is 32

这种类型的结果存在多个问题。首先,我正在尝试构建一个交互式控制台。所以对于上面的例子,管道需要并行工作。但是,在关闭管道 [0] 之前,我无法检索管道 [1]。因为如果我在代码的前面获得管道[1] 的值,程序就会挂起。在这种情况下。首先,我需要能够读取“输入您的姓名:”输入,然后输入“标记”输入。接下来的步骤类似我需要获取文本“输入年龄:”并输入输入“32”。最后我需要得到最终输出,即“马克,你的年龄是 32 岁”并检测程序是否完成,然后关闭两个管道。这可能吗?

【问题讨论】:

    标签: java php console user-input


    【解决方案1】:

    使用 proc_open 而不是 exec。它可用于检索到stdin 的管道,该管道可用于为您的Java 应用程序提供输入。 proc_open 手册页上的第一个示例演示了如何执行此操作。

    【讨论】:

    • 我再次编辑了这个问题。按照建议使用了 proc_open 命令。请您检查一下我的代码和输出,并建议我哪里出错了?提前谢谢..
    • 我猜你实际上是在第一个输入中输入两个值。尝试像这样添加新行:fwrite($pipes[0], "Mark\n"); fwrite($pipes[0], "32\n");
    • 感谢您的建议。但是,我还有一个问题。我用新信息更新了问题。非常感谢您的支持。
    【解决方案2】:

    关于您的更新,也许使用fread 而不是stream_get_contentsfread 应该只读取可用的内容,而stream_get_contents 将阻塞,直到保证流中不再有可读数据。如果您想在程序终止之前获得stdout,请尝试这样的操作。

    $line_limit = 1024;
    echo fread($pipes[1], $line_limit);
    fwrite($pipes[0], "Mark\n");
    echo fread($pipes[1], $line_limit);
    fwrite($pipes[0], "32\n");
    echo fread($pipes[1], $line_limit);
    fclose($pipes[0]);
    fclose($pipes[1]);
    

    唯一需要注意的是,如果您在 Java 程序完成输出之前尝试读取数据,那么您可能无法获得您期望的所有输出(可能什么也没有)。如果您遇到这种情况,我会在写入和读取之间添加延迟(sleep)。

    如果您想要一个真正的交互式终端,那么您可能必须生成一个后台线程,不断轮询stdout 以获取更多数据,但这可能最好在另一个问题中提出。

    【讨论】:

    • 非常感谢。您的代码运行良好。但令我震惊的一件事是我如何区分需要用户输入的问题和程序的最终输出。基本上我需要知道程序最终输出何时打印以及java程序何时完成? (因为我们目前对问题和最终结果使用同一行代码 - fread($pipes[1], $line_limit); )
    • @AvinashD 您可以使用proc_get_status($proc)["running"] 检查进程是否正在运行或终止。请注意,关闭进程可能需要相当长的时间,因此您可能需要某种延迟。也许在它之前有一个sleep(1)
    • 非常感谢您的帮助!它帮助了我很多,也节省了很多时间。 :)
    • 你好克里斯.. 请检查链接中的问题,如果可能,请提供一些示例代码以继续。提前致谢。 [链接:]stackoverflow.com/questions/36347269/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多