I want to execute java programs using php code. When i write the below code, the program written in the editor is getting compiled and executed successfully.
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
Note: $output
and $check
variables contains required input to compile & run
But, when I try to execute java programs where we need to input some data to contine with the execution, the above code doesn't works. For example, consider the JavaScannerExample
in the link: http://alvinalexander.com/java/edu/pj/pj010005
To execute the program in the link, I guess I need some interactive console to accept the input and continue with program execution. Please suggest me how to achieve this using php?
Update:
@Chris.. Tried proc_open
command as suggested. See my code below:
PHP Code
<?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 Code
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 Output
Enter your name: Enter your age:
Could you please check and let me know where did I went wrong?
Update2:
@Chris.. Thanks for your suggestion. It helped me get the output.
Here is the modified php code:
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;
}
This is the result I am getting.
Enter your name: Enter your age: Mark, your age is 32
There are multiple problems with this type of result. First I am trying to build an interactive console. So for the above example, the pipes need to work in parallel. However, I am not able to retrieve pipes[1] until I close pipes[0]. Because if I get the value of pipes[1] earlier in the code the program is hanging. In this scenario. First I need to be able to read the input which is "Enter your name:" Then enter input which is "Mark". Next steps are similar I need to get the text "Enter age:" and enter input "32". finally I need to get the final output which is "Mark, your age is 32" and detect the program is finished and then close both the pipes. Is this possible?
Use proc_open instead of exec. It can be used to retrieve a pipe to stdin
which can be used to provide input to your Java application. The first example on the proc_open
manual page demonstrates how to do this.
With regards to your update, maybe use fread
instead of stream_get_contents
. fread
should only read what is available, whereas stream_get_contents
will block until there is guaranteed to be no more readable data in the stream. If you want to get stdout
before the program has terminated, try something like this.
$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]);
The only thing to watch out for is if you try and read data before the Java program has finished outputting it then you might not get all the output you expect (possibly nothing at all). If you experience this, I'd add a delay (with sleep
) between the writes and the reads.
If you want a truly interactive terminal then you will probably have to spawn a background thread that constantly polls stdout
for more data, but that's potentially best asked about in another question.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.