【问题标题】:java: how to both read and write to & from process thru pipe (stdin/stdout)java:如何通过管道(stdin/stdout)从进程中读取和写入
【发布时间】:2011-05-05 23:26:45
【问题描述】:

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

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

【问题讨论】:

  • 如果您可以为这两个过程提供一个简短但完整的示例,那真的很有帮助。基本上是一种重现行为的方法。

标签: java pipe stdin


【解决方案1】:

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

一旦我从我从 Java 获得的行中剥离()额外的 0xA0,python 在返回的路上向 Java 添加了一个“正常”\n,并且事情运行顺利。

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

【讨论】:

  • 啊,很高兴你解决了 :) 希望我们的错误答案在此过程中仍然有用...
  • @BerryTsakala,它工作得很好,但如果返回的字符串跨越多行,那么似乎有问题。此外,如果输入错误,您还需要有 errorStream。我正在尝试使用您的想法,但是在使用不同的程序时遇到了一些问题,我想应该在这里使用线程,知道吗??
  • Java 代码中没有发送0xA0 的内容,并且0xA0 不是行终止符。 0x0A 是一个换行符,如果这就是你的意思的话。
【解决方案2】:

我认为问题出在您调用的过程中:

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

我怀疑readline 会读取该行,但s包含行终止符。然后,您正在打印该行,但是 没有行终止符...Java 会阻塞,直到它读取行终止符,这将永远阻塞,因为进程不是' t给一个。

这只是一个猜测,因为我并不完全清楚您调用的进程使用哪种语言 - 如果print 实际上确实输出了一个行终止符,那么这是一个错误的猜测。但是,如果没有,您可能需要将其更改为:

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

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

【讨论】:

  • 如果是这样的话,第二个代码块(被报告为工作)会工作吗?看起来它与行尾没有什么不同。
  • @Sean:第二个代码块最初发送三个换行符,所以进程将在写入“AaaaaBbbbbb”后终止。此时,readLine() 将看到输入流的结尾,并将数据计数为最后一行。请注意,这也解释了为什么 "\n\n" 在第一种情况下有效,但随后返回一个空的第二个字符串。
  • 如果没有打印换行符,这不会导致工作示例在单行上输出 AAAAbbbb 吗?
  • @Sean:嗯,是的,你是对的。不知道这是怎么回事。不幸的是,我现在无法调查。
  • Python的“print”语句自动添加换行符,大致相当于Java的println
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多