Java中分叉子进程的输出

时间:2011-08-31 16:12:57

标签: java process input

我正在从Java程序中执行Native窗口中的cmd进程。我希望能够查看分叉进程的输入和输出。但是,我似乎无法从Java程序中编写任何内容。

当我尝试在Windows中的命令提示符上写一组字符时,我有点期待它在屏幕上打印一些东西 - 任何东西。所以,如果我给它荒谬的垃圾,那么它应该打印它不理解该命令。

但是,在将以下代码中的垃圾String写入子进程的OutputStream之后:

Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("cmd");
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
PrintWriter out = new PrintWriter(process.getOutputStream());
String line = null;
out.println("My Garbage String");
while((line = readLine()) != null)
    System.out.println(line);

程序在while((line = readLine()) != null)处停止。

因此,父进程显然是阻塞的,直到子进程获得一些输入并解除阻塞并将该输入发送到父进程。但是,当我在PrintWriter的{​​{1}}方法上写任何内容时,我正在给孩子处理一些输入,不是吗?

更新

现在,由于给我的一些答案,我决定澄清我的问题是什么。我可以从命令提示符中读取输出。实际上,当我第一次运行它时,如果在命令提示符下键入“cmd”,我将获得与通常获得的相同的输出。

例如,请使用以下代码示例:

println()

代码的输出如下:

  

Microsoft Windows XP [版本5.1.2600](C)版权所有1985-2001   微软公司

如您所见,命令提示符为我的父进程提供了一些输出。但是,在我的IDE中以调试模式运行它时,我发现它只是停在Process process = Runtime.getRuntime().exec("cmd"); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); PrintWriter out = new PrintWriter(process.getOutputStream()); String line = null; do { line = in.readLine(); System.out.println(line); }while(line!=null) 行。因此,子进程阻塞,因为没有其他内容可以打印。

因此,当我尝试使用其line=in.readLine();属性为其提供一些输入时,它似乎没有响应。相反,程序会阻塞OutputStream

回应一张海报建议的内容,你提到的文章(当Runtime.exec()不会)时,它只会从line=in.readLine();和{{ 1}}属性。除了运行OutputStream时以数组形式给出的初始执行参数之外,它没有提到我可以给它任何类型的输入。

为了模拟我最初想要做的事情(即,给它随机垃圾并打印它不理解命令),我可以只需输入ErrorStream我的代码并运行它。但是,这不是我想要做的。我希望在它已经开始执行后与命令提示符进行通信。

最终,我希望能够与其他程序进行交互,这些程序通常需要您在从Java程序执行后与它们进行交互。然而,如果我能告诉它该做什么的唯一一次是当我指定其执行参数时,那么我将无法以我想要的方式使用Java与单独的进程交互。

如果有人知道如何实现这一目标,请告诉我。感谢。

5 个答案:

答案 0 :(得分:3)

StreamGobbler是谷歌为他们提供的方式。它们以新线程开始并正在读取输出。

一篇描述如何实现它们的好文章。 When Runtime.exec() won't

答案 1 :(得分:2)

这里有完整的样本。请注意,这会通过输出流运行dir命令。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

class StreamGobbler extends Thread {
InputStream is;
String type;

StreamGobbler(InputStream is, String type) {
    this.is = is;
    this.type = type;
}

public void run() {
    try {
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String line = null;
        while ((line = br.readLine()) != null)
            System.out.println(type + ">" + line);
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}
}

public class GoodWindowsExec {
public static void main(String args[]) {


    try {
        String osName = System.getProperty("os.name");
        String[] cmd = new String[1];

        cmd[0] = "cmd.exe";

        Runtime rt = Runtime.getRuntime();

        Process proc = rt.exec(cmd);


        proc.getOutputStream().write("dir \n".getBytes());
        proc.getOutputStream().flush();
        // any error message?
        StreamGobbler errorGobbler = new StreamGobbler(
                proc.getErrorStream(), "ERROR");

        // any output?
        StreamGobbler outputGobbler = new StreamGobbler(
                proc.getInputStream(), "OUTPUT");

        // kick them off
        errorGobbler.start();
        outputGobbler.start();

        // any error???
        int exitVal = proc.waitFor();
        System.out.println("ExitValue: " + exitVal);
    } catch (Throwable t) {
        t.printStackTrace();
    }
}
}

答案 2 :(得分:1)

Java程序控制process.getOutputStream()的输入。如果要将数据发送到程序,则需要从Java发送数据。

答案 3 :(得分:0)

你很困惑。 首先,当前的描述是混乱的,你应该重写它。

其次,按照 Farmor 的回答提供StreamGobbler。

您对

的期望是什么?
out.println("My Garbage String"); 
while((line = readLine()) != null)
...

它完全符合它所说的。将字符串发送到外部进程的输入流,而不是在相同的输入流中等待任何字符串到达​​。你之前寄过的那个当然是早已不复存在

答案 4 :(得分:0)

“程序停在它所说的位置((line = readLine())!= null)。”

答案可能是单独的问题Java Process with Input/Output Stream(来自Luke Woodward的回答):

  

..循环while((line = readLine())!= null)   只有在读取器退出时才会从进程的标准中读取   输出,返回文件结尾。 只有在流程退出时才会发生这种情况。   如果目前没有发生,它将不会返回文件结尾   来自流程的更多输出。相反,它将等待下一行   来自流程的输出,直到它有下一行才返回。

尝试使用一个线程将命令写入process.getOutputStream(),然后使用第二个线程读取process.getInputStream()。