I am working on a simple java program. It simply compiles and executes another java program. I am using Runtime.exec() function to compile and run. There is no problem with compilation. but when it runs, if the second program needs an input to read from keyboard, I can’t give it from the master process. I used getOutputStream() function. but it couldn’t help. I will provide my code.
public class sam { public static void main(String[] args) throws Exception { try { Process p = Runtime.getRuntime().exec("javac sam2.java"); Process p2 = Runtime.getRuntime().exec("java sam2"); BufferedReader in = new BufferedReader( new InputStreamReader(p2.getInputStream())); OutputStream out = p.getOutputStream(); String line = null; line = in.readLine(); System.out.println(line); input=input+"\n"; out.write(input.getBytes()); p.wait(10000); out.flush(); }catch (IOException e) { e.printStackTrace(); } } }
This is my master program(sam.java).
The following is the code of sam2.java
public class sam2 { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; System.out.println("Enter the number..\n"); str = br.readLine(); System.out.println(Integer.parseInt(str)); } }
There is no problem, if my second program has only printing statements. But the problem arises when I have to read something from the other.
The issue you are facing is because you are trying to interact with the standard input/output streams of the second Java program (sam2.java) in a way that is not suitable for your use case.
sam2.java
When you use Runtime.getRuntime().exec("java sam2"), it starts a new process for sam2.java, and you try to get its output stream and write to it. However, the second program is waiting for input from the console, and you are trying to provide that input through the output stream, which is not the correct approach.
Runtime.getRuntime().exec("java sam2")
Instead, you should use the ProcessBuilder class, which allows you to redirect the standard input, output, and error streams of the child process. Here’s an example of how you can modify your sam.java program:
ProcessBuilder
sam.java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; public class sam { public static void main(String[] args) { try { // Compile sam2.java Process compileProcess = new ProcessBuilder("javac", "sam2.java").start(); int compileExitCode = compileProcess.waitFor(); if (compileExitCode == 0) { // Run sam2.java Process runProcess = new ProcessBuilder("java", "sam2").start(); // Get the input stream of the child process OutputStream childInputStream = runProcess.getOutputStream(); // Provide input to the child process String input = "123\n"; // You can change this input as needed childInputStream.write(input.getBytes()); childInputStream.flush(); // Wait for the child process to complete int runExitCode = runProcess.waitFor(); // Print the output of the child process BufferedReader in = new BufferedReader(new InputStreamReader(runProcess.getInputStream())); String line; while ((line = in.readLine()) != null) { System.out.println(line); } // Print the exit code of the child process System.out.println("Exit Code: " + runExitCode); } else { System.out.println("Compilation failed"); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }
This modified code uses ProcessBuilder to start the child processes and redirect their input and output streams. The input for the child process is provided through the output stream, and the output of the child process is read from its input stream. Note that you should handle exceptions appropriately in a production code, and this example simplifies error handling for illustration purposes.