Java: как читать и писать в и из процесса через канал (стандартный / стандартный вывод) - PullRequest
4 голосов
/ 06 ноября 2010

(я новичок в Java) Мне нужно запустить процесс и получить 2 или 3 дескриптора: для STDIN, STDOUT (и STDERR), чтобы я мог записывать ввод в процесс и получать его вывод так же, как ведут себя каналы командной строки (например, «grep») 1001 *

в Python это достигается с помощью следующего кода:

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()

Что такое эквивалент Java?

Я уже пробовал

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();

Кстати, первая попытка работает только с \ n \ n, но не работает с одним \ n (почему?)

следующий код работает, но все входные данные даны заранее, а не поведение, которое я ищу:

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 );

выход:

response1: AAAAA
response2: 
response3: bbbbbb
response4: 

запускаемый процесс выглядит так:

s = sys.stdin.readline()
print s.upper()
s = sys.stdin.readline()
print s.lower()

Ответы [ 2 ]

9 голосов
/ 06 ноября 2010

Хорошо, это была также ошибка кода моего питона, но в отличие от ответа @ Jon, была ДОПОЛНИТЕЛЬНАЯ новая строка (0xA0, если быть точным, что не является стандартом Windows).

как только яstrip (), извлекая дополнительные 0xA0 из строки, которую я получаю из Java, python добавляет один «обычный» \ n в Java на обратном пути, и все идет гладко.

для полноты вопроса и ответаВот рабочий код Java:

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();
    }
    }
}

и это код Python

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()
2 голосов
/ 06 ноября 2010

Я полагаю, что проблема в процессе, который вы вызываете:

s = sys.stdin.readline()
print s.upper()
s = sys.stdin.readline()
print s.lower()

Я подозреваю, что readline собирается прочитать строку, но s будет не включатьтерминатор строки.Затем вы печатаете эту строку, но без ограничителя строки ... Java блокирует до тех пор, пока не прочитает разделитель строки, который будет блокироваться навсегда, так как процесс не даетодин.

Это все немного догадка, так как мне не совсем ясно, на каком языке находится ваш вызываемый процесс - если print на самом деле действительно выводит терминатор строки, то этоневерное предположение.Однако, если нет, вам может потребоваться изменить его на что-то вроде:

s = sys.stdin.readline()
println s.upper()
s = sys.stdin.readline()
println s.lower()

РЕДАКТИРОВАТЬ: Это не объясняет пустых строк в примере вывода ... не знаю, что происходит, на самом деле, но к сожалениюЯ не могу сейчас смотреть на это.

...