java: how to both read and write to & from process thru pipe (stdin/stdout)
(i'm new to java) I need to start a process and receive 2 or 3 handles: for STDIN, STDOUT, (and STDERR), so I can write input to the process and receive its output, the same way command line pipes behave (e.g. "grep")
in Python this is acheived with the following code:
from subprocess import Popen, PIPE
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
child_stdin.write('Yoram Opposum\n')
child_stdin.flush()
child_stdout.readlines()
What's the Java equivalent??
I've tried so far
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader inp = new BufferedReader( new InputStreamReader(p.getInputStream()) );
BufferedWriter out = new BufferedWriter( new OutputStreamWriter(p.getOutputStream()) );
out.write( "Some Text!\n\n" );
out.flush();
line = inp.readLine();
print("response1: " + line ); // that's ok
out.write( "Second Line...\n" );
out.flush();
line = inp.readLine();
print("response2: " + line ); // returns an empty string, if it returns,,,
inp.close();
out.close();
BTW the first try works only with \n\n, but doesn't work with single \n (why?)
the following code works, but all input is given in advance, not the behavior i'm looking for:
out.write( "Aaaaa\nBbbbbb\nCcccc\n" );
out.flush();
line = inp.readLine();
print("response1: " + line );
line = inp.readLine();
print("response2: " + line );
line = inp.readLine();
print("response3: " + line );
line = inp.readLine();
print("response4: " + line );
output:
response1: AAAAA
response2:
response3: bbbbbb
response4:
the process being run looks like that:
s = sys.stdin.readline()
print s.upper()
s = sys.stdin.readline()
print s.lower()
ok, it was also my python's code fault, but opposite to @Jon's answer, there was an EXTRA newline (0xA0 to be exact, which isn't Windows' standard).
once i'm strip()ing the extra 0xA0 from the line i get from Java, python adds a single "normal" \n to Java on the way back, and things run smoothly.
for the completeness of the question and answer, here's a working Java code:
import java.io.*;
import java.util.*;
public class Main {
public static BufferedReader inp;
public static BufferedWriter out;
public static void print(String s) {
System.out.println(s);
}
public static String pipe(String msg) {
String ret;
try {
out.write( msg + "\n" );
out.flush();
ret = inp.readLine();
return ret;
}
catch (Exception err) {
}
return "";
}
public static void main(String[] args) {
String s;
String cmd = "c:\\programs\\python\\python.exe d:\\a.py";
try {
print(cmd);
print(System.getProperty("user.dir"));
Process p = Runtime.getRuntime().exec(cmd);
inp = new BufferedReader( new InputStreamReader(p.getInputStream()) );
out = new BufferedWriter( new OutputStreamWriter(p.getOutputStream()) );
print( pipe("AAAaaa") );
print( pipe("RoteM") );
pipe("quit")
inp.close();
out.close();
}
catch (Exception err) {
err.printStackTrace();
}
}
}
and this is the python code
import sys
s = sys.stdin.readline().strip()
while s not in ['break', 'quit']:
sys.stdout.write(s.upper() + '\n')
sys.stdout.flush()
s = sys.stdin.readline().strip()
I believe the problem is in the process you're calling:
s = sys.stdin.readline()
print s.upper()
s = sys.stdin.readline()
print s.lower()
I suspect that readline
is going to read the line but s
will not include the line terminator. You're then printing that line, but without a line terminator... Java is then blocking until it reads a line terminator, which will block forever as the process isn't giving one.
This is all a bit of a guess as it's not exactly clear to me what language your called process is in - if print
actually does output a line terminator, then it's an incorrect guess. However, if not, you may need to change it to something like:
s = sys.stdin.readline()
println s.upper()
s = sys.stdin.readline()
println s.lower()
EDIT: That doesn't explain the blank lines in sample output... no idea what's going on, really, but unfortunately I can't look into it now.