【问题标题】:Output of forked child process in JavaJava中分叉子进程的输出
【发布时间】:2011-11-07 18:32:24
【问题描述】:

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

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

但是,在以下代码中将我的垃圾字符串写入子进程的 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)处停止。

因此,父进程显然是阻塞的,直到子进程获得一些输入并解除阻塞并将该输入发送到父进程。但是,当我将任何内容写入PrintWriterprintln() 方法时,我正在给子进程一些输入,不是吗?

更新

现在,由于得到了一些答案,我决定澄清我的问题所在。我可以很好地读取命令提示符的输出。事实上,当我第一次运行它时,我得到的输出与在命令提示符下键入“cmd”时通常得到的输出相同。

例如,下面的代码示例:

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)

代码的输出如下:

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

如您所见,命令提示符正在为我的父进程提供一些输出。但是,在我的 IDE 中以调试模式运行它时,我发现它只是简单地停在 line=in.readLine(); 行。因此,子进程阻塞,因为没有其他内容可打印。

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

为了回应一位发帖者的建议,您提到的文章(当 Runtime.exec() 不会),它只是从 OutputStreamErrorStream 属性中获取输出.它没有提到除了在运行Runtime.exec(args) 时以数组形式给出的初始执行参数之外,我如何给它任何类型的输入。

为了模拟我最初想要做的事情(即给它随机垃圾并让它打印出它不理解该命令),我可以只需在我的代码中输入Runtime.getRumtime().exec("cmd /c random garbage);并运行它。但是,这不是我想做的。我想在它已经开始执行后与命令提示符进行通信。

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

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

【问题讨论】:

  • 投反对票,因为这不是“Java 子进程”问题,而是我在回答中描述的基本编程理解问题。
  • 你应该为你的问题选择一个答案

标签: java process input


【解决方案1】:

StreamGobblers 是为他们使用谷歌的方式。它们从新线程开始并读取输出。

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

【讨论】:

  • 读取输出对我来说根本不是问题。我的问题是 input.
【解决方案2】:

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

【讨论】:

  • 我不明白你在说什么。这不是完全我在做什么吗???你读过我的示例代码吗?
  • 我又读了一遍代码,看不到你写给out的地方。你能指出来吗?
【解决方案3】:

这里有一个完整的示例。请注意,这会通过输出流运行 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();
    }
}
}

【讨论】:

  • 在这里,您正在使用 OutputStream 的 write 方法写入命令提示符,并将带有行终止字符的命令作为一组字节写入该方法。我一直在使用 OutputStream 的 println 方法并在没有行终止字符的情况下编写字符串,并且严格作为字符串。一直都是我的问题???我可以写入外部程序的唯一方法是将一系列字节写入 OutputStream 的 write 方法?
【解决方案4】:

你把事情弄糊涂了。 首先,目前的描述很混乱,你应该重写它。

其次,按照 Farmor 的回答中提供的 StreamGobbler 进行操作。

你有什么期望

out.println("My Garbage String"); 
while((line = readLine()) != null)
...

?

它完全按照它所说的去做。将字符串发送到外部进程的输入流,而不是在同一输入流中等待任何字符串到达​​。当然,您之前发送的那个在当时早已不复存在了。

【讨论】:

  • 因为他没有刷流,所以没有发送。
  • 我不确定你是否必须刷新它,但它不会改变任何东西。他使用的代码没有意义。
【解决方案5】:

“程序停在它说的地方 while((line = readLine()) != null)。”

答案可能在单独的问题Java Process with Input/Output Stream(来自卢克伍德沃德的回答):

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

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

【讨论】:

    猜你喜欢
    • 2011-06-24
    • 2015-12-12
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    相关资源
    最近更新 更多