Home >Java >javaTutorial >How to Properly Handle Input/Output Streams in Java Processes to Avoid Blocking?
Java Process with Input/Output Stream
Consider the following code snippet:
Scanner scan = new Scanner(System.in); Process process = Runtime.getRuntime().exec("/bin/bash"); OutputStream stdin = process.getOutputStream(); InputStream stderr = process.getErrorStream(); InputStream stdout = process.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(stdout)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin)); String input = scan.nextLine(); input += "\n"; writer.write(input); writer.flush(); input = scan.nextLine(); input += "\n"; writer.write(input); writer.flush(); while ((line = reader.readLine()) != null) { System.out.println("Stdout: " + line); } input = scan.nextLine(); input += "\n"; writer.write(input); writer.close(); while ((line = reader.readLine()) != null) { System.out.println("Stdout: " + line); }
This code allows you to enter a command in the bash shell and receive its output. However, after the initial input and output, subsequent inputs do not result in the expected output.
Why This Occurs
The issue arises because the code does not correctly handle the end-of-file (EOF) condition for the standard output of the bash process. The loop while ((line = reader.readLine()) != null) will only exit when the process exits, which means that if there is no further output from the process, the loop will block indefinitely.
Proposed Solution - ProcessBuilder and --EOF-- Handling
To address this issue, consider the following modifications:
ProcessBuilder builder = new ProcessBuilder("/bin/bash"); builder.redirectErrorStream(true); Process process = builder.start();
By using ProcessBuilder instead of Runtime.getRuntime().exec(), you can redirect the standard error of the bash process to its standard output, ensuring that you only need one input stream.
Additionally, the code can be modified to send a special delimiter, --EOF--, to signal the end of the output from a command. This allows the code to reliably separate the output from multiple commands.
while (scan.hasNext()) { String input = scan.nextLine(); if (input.trim().equals("exit")) { // Putting 'exit' amongst the echo --EOF--s below doesn't work. writer.write("exit\n"); } else { writer.write("((" + input + ") & echo --EOF-- || echo --EOF--)\n"); } writer.flush(); line = reader.readLine(); while (line != null && !line.trim().equals("--EOF--")) { System.out.println("Stdout: " + line); line = reader.readLine(); } }
With these changes, the code will reliably handle multiple commands and their output, providing the desired functionality.
The above is the detailed content of How to Properly Handle Input/Output Streams in Java Processes to Avoid Blocking?. For more information, please follow other related articles on the PHP Chinese website!