11

(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()
1
  • If you could give a short but complete example for both processes, that would really help. Basically a way to reproduce the behaviour. Commented Nov 6, 2010 at 13:24

2 Answers 2

12

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()
Sign up to request clarification or add additional context in comments.

4 Comments

Ah, glad you've worked it out :) Hope our incorrect answers were still useful along the way...
@BerryTsakala, well it works but what if the returned String is spanning over multiple lines, then there seem to be problem. Also if there is wrong input, you would need to have errorStream as well. I am trying to use your idea but having some problem with different programs, i guess should use threads here, any idea??
There is nothing in your Java code that sends 0xA0, and 0xA0 is not a line terminator. 0x0A is a line feed, if that's what you mean.
To make the Python code a bit cleaner: duplicating s = sys.stdin.readline().strip() can be replaced by a single call using the walrus operator within the loop condition: while (s := sys.stdin.readline().strip()) not in ['break', 'quit']:.
3

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.

9 Comments

Would the second block of code (that is reported as working), work if that was the case? It doesn't look like it does anything different with line endings.
@Sean: The second block of code is initially sending three line feeds, so the process will terminate after writing "AaaaaBbbbbb". At that point, readLine() will see the end of the input stream, and count the data so far as a final line. Note that this also explains why "\n\n" works in the first case, but then returns an empty second string.
Wouldn't that cause the working example to output AAAAbbbb on a single line, if there were no line breaks being printed?
@Sean: Hmm, yes, you're right. No idea how that's happening. Unfortunately I can't look into it now.
Python's "print" statement adds a newline automatically, and is roughly equivalent to Java's println
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.