【问题标题】:How to read the std output of another java program in this java program?如何在这个java程序中读取另一个java程序的std输出?
【发布时间】:2013-11-14 03:06:25
【问题描述】:

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

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”。

【问题讨论】:

  • 主要是因为到了输入流的末尾。这表明进程失败并已将原因写入错误流,但您没有阅读它。

标签: java command-line std


【解决方案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 是您的路径,这将起作用,否则您将需要提供可执行文件的完整路径,就像您在示例中所做的那样;)

【讨论】:

    【解决方案2】:

    首先,您的程序是完全正确的。我的意思是你启动进程和读取输入流的方式应该工作。那么让我们看看为什么它没有。

    我运行了你的程序,我遇到了同样的行为。为了理解它为什么不起作用,我做了一个简单的改变:我没有阅读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。这清楚地表明该进程已提前终止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      相关资源
      最近更新 更多