2

我有以下类文件。这将启动命令提示符并打印响应。奇怪的是在第一次打印之后,即 dir 后续不打印。请指教。

import java.io.*;
public class JavaApplication14 {
static Process p;

public static void main(String[] args) {
    try {
        String line;

        p = Runtime.getRuntime().exec("cmd.exe");
        OutputStream stdin = p.getOutputStream();
        InputStream stderr = p.getErrorStream();
        InputStream stdout = p.getInputStream();

        BufferedReader reader = new BufferedReader(new InputStreamReader(stdout));
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(stdin));

        String input = "dir";
        input += "\n";
        writer.write(input);
        writer.flush();



        while ((line = reader.readLine()) != null) {
            System.out.println("Stdout: " + line);
        }
         input = "cd..";
        input += "\n";
        writer.write(input);
        writer.flush();
        input = "dir";
        input += "\n";
        writer.write(input);
        writer.close();

        while ((line = reader.readLine()) != null) {
            System.out.println("Stdout: " + line);
        }
    } catch (IOException ex) {
        Logger.getLogger(JavaApplication14.class.getName()).log(Level.SEVERE, null, ex);
    }
 }
 }
4

2 回答 2

4

您的(第一个)while()循环永远不会终止:

while ((line = reader.readLine()) != null) {
    System.out.println("Stdout: " + line);
}

readLine()当流关闭时返回null,但由于您的子进程仍在运行,因此流永远不会关闭。

为了解决这个问题,您可以将读取部分移动到单独的线程中(这需要额外的同步),或者更简单的解决方案是查看是否读取了特定的行内容,例如,如果命令行提示符是由以下内容打印的cmd.exe

while ( !(line = reader.readLine()).startsWith("C:\\") ) {
    System.out.println("Stdout: " + line);
}

这应该适用于您的特定用例,并且可能足以进行一些学习 - 对于实际应用程序,您可能希望查看Apache Commons Exec项目。

于 2013-06-24T11:24:00.007 回答
2

您正在尝试使用同步 I/O 操作从一个线程中完成根本上的异步工作。你的方法注定会失败。

具体来说,readLine()阻塞直到有整行要读取,或者直到底层流关闭。

您必须编写更多涉及线程的代码才能完成这项工作。这是Java中的一个痛点。

您还可以使用ProcessBuilder,尤其是其redirectOutput带有参数值的方法INHERIT,以使子进程继承您的主进程的stdout. 在这种情况下,您将没有机会在 Java 中分析子流程的输出。

于 2013-06-24T11:25:48.017 回答