java:如何通过管道(stdin/stdout)读写进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4112470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 11:44:41  来源:igfitidea点击:

java: how to both read and write to & from process thru pipe (stdin/stdout)

javapipestdin

提问by Berry Tsakala

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

(我是 Java 新手)我需要启动一个进程并接收 2 或 3 个句柄:对于 STDIN、STDOUT(和 STDERR),因此我可以将输入写入进程并接收其输出,就像命令行管道一样行为(例如“grep”)

in Python this is acheived with the following code:

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

What's the Java equivalent??

Java 等价物是什么?

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

顺便说一句,第一次尝试仅适用于 \n\n,但不适用于单个 \n(为什么?)

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

采纳答案by Berry Tsakala

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

好的,这也是我的 python 代码错误,但与@Jon 的回答相反,有一个额外的换行符(确切地说是 0xA0,这不是 Windows 的标准)。

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.

一旦我从我从 Java 得到的行中去除了额外的 0xA0,python 在回来的路上向 Java 添加了一个“普通”\n,并且事情运行顺利。

for the completeness of the question and answer, here's a working Java code:

为了问题和答案的完整性,这是一个有效的 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();
    }
    }
}

and this is the python code

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

回答by Jon Skeet

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 readlineis going to read the line but swill notinclude the line terminator. You're then printing that line, but without a line terminator... Java is then blocking until it readsa line terminator, which will block forever as the process isn't giving one.

我怀疑readline是要读取的行,但s包括行终止。然后您将打印该行,但没有行终止符……然后 Java 会阻塞,直到它读取一个行终止符,因为进程没有给出行终止符,该终止符将永远阻塞。

This is all a bit of a guess as it's not exactly clear to me what language your called process is in - if printactually doesoutput a line terminator, then it's an incorrect guess. However, if not, you may need to change it to something like:

这是所有有点猜的,因为它是不完全清楚,我叫你的过程是什么语言-如果print确实输出行结束符,那么它是不正确的猜测。但是,如果没有,您可能需要将其更改为:

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.

编辑:这并不能解释示例输出中的空行......不知道发生了什么,真的,但不幸的是我现在无法研究它。