如何在这个java程序中读取另一个java程序的std输出?

时间:2013-11-14 03:06:25

标签: java command-line std

我编写了一个简单的Java程序,它每5秒向std输出一些“hello”。

public class DDD {
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; ; i++) {
            System.out.println("hello " + i);
            Thread.sleep(5000);
        }
    }
}

然后我编译它并获得.class。

我编写另一个java程序来运行它并获得输出:

public static void main(String[] args) throws Exception {
    String command = "c:\\java\\jdk1.7.0_07\\bin\\java mytest.DDD";
    Process exec = Runtime.getRuntime().exec(command);

    BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
    while (true) {
        String line = reader.readLine();
        System.out.println(line);
        if (line == null) {
            Thread.sleep(1000);
        }
    }
}

但它始终打印:

null
null
null
null
null
null
null

哪里错了?我的操作系统是“Windows XP”。

2 个答案:

答案 0 :(得分:1)

首先,你的程序是完全正确的。我的意思是你启动流程并读取输入流 的方式。所以,让我们看看它为什么没有。

我运行了你的程序,我遇到了同样的行为。为了理解它为什么不起作用,我做了一个简单的改变:我没有阅读getInputStream(),而是听了getErrorStream()。这样,我可以看到java命令是否返回错误而不是启动程序。果然,它打印了以下信息:

Error: Could not find or load main class myTest.DDD

就是这样,我猜你也可能就是这种情况。该程序可能根本找不到DDD类,因为它不在类路径中。

我在Eclipse中工作,并且这些类被编译到项目中的目录bin中,所以我只是将命令更改为

String command = "c:\\java\\jdk1.7.0_07\\bin\\java -cp bin mytest.DDD";

它有效。我获得了(在切换回getInputStream()之后):

hello 0
hello 1
hello 2
hello 3

这意味着默认情况下,命令exec生成的进程的工作目录是项目的根目录,而不是编译类的目录。

总之,只需指定类路径,它应该可以正常工作。如果没有,请查看错误流包含的内容。

注意:您可能已经猜到了原因:如果已到达流的末尾,则Javadoc指定readline()返回null。这是一个明确的指标,表明该过程提前终止。

答案 1 :(得分:1)

BufferedReader#readLine会在到达流的末尾时返回null

因为你基本上忽略了这个退出指示器并在无限循环中循环,所以你得到的只是null

可能的原因是因为该进程已向错误流输出一些错误信息,而您没有阅读...

您应该尝试使用ProcessBuilder,这样您就可以将错误流重定向到输入流

try {
    String[] command = {"java.exe", "mytest.DDD"};
    ProcessBuilder pb = new ProcessBuilder(command);
    // Use this if the place you are running from (start context)
    // is not the same location as the top level of your classes
    //pb.directory(new File("\path\to\your\classes"));
    pb.redirectErrorStream(true);
    Process exec = pb.start();

    BufferedReader br = new BufferedReader(new InputStreamReader(exec.getInputStream()));
    String text = null;
    while ((text = br.readLine()) != null) {
        System.out.println(text);
    }
} catch (IOException exp) {
    exp.printStackTrace();
}

ps-如果java.exe是您的路径,这将有效,否则您将需要像您在示例中所做的那样提供可执行文件的完整路径;)