简体   繁体   English

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

[英]How to read the std output of another java program in this java program?

I write a simple Java program, which just output some "hello"s to std every 5s. 我写了一个简单的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);
        }
    }
}

Then I compile it and getting a .class. 然后我编译它并获得.class。

I write another java program to run it and get the output: 我编写另一个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);
        }
    }
}

But it always prints: 但它始终打印:

null
null
null
null
null
null
null

Where is wrong? 哪里错了? My os is "windows XP". 我的操作系统是“Windows XP”。

First, your program is totally correct. 首先,你的程序是完全正确的。 By that I mean the way you launch the process and read the input stream should work. 我的意思是你启动进程的方式和读取输入流应该工作。 So let's see why it doesn't. 所以让我们看看它为什么没有。

I ran your program and I encountered the same behavior. 我运行你的程序,我遇到了同样的行为。 To understand why it didn't work, I made a simple change: instead of reading getInputStream() , I listened to getErrorStream() . 为了理解它为什么不起作用,我做了一个简单的改变:我没有读取getInputStream() ,而是听了getErrorStream() This way, I could see if the java command returned an error instead of launching the program. 这样,我可以看到java命令是否返回错误而不是启动程序。 And sure enough, it printed the following message: 果然,它打印了以下消息:

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

That's it, and I guess it's probably the case for you too. 就是这样,我猜你也可能就是这种情况。 The program could simply not find the DDD class because it's not in the classpath. 程序可能根本找不到DDD类,因为它不在类路径中。

I work in Eclipse and the classes are compiled into the directory bin in the project, so I simply changed the command to 我在Eclipse中工作,并且类被编译到项目中的目录bin中,所以我只是将命令更改为

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

and it worked. 它起作用了。 I obtained (after switching back to getInputStream()): 我获得了(在切换回getInputStream()之后):

hello 0
hello 1
hello 2
hello 3

This means that by default the working directory for processes spawned by the command exec is the root of the project, not the directory where the classes are compiled. 这意味着默认情况下,命令exec生成的进程的工作目录是项目的根,而不是编译类的目录。

In conclusion, just specify the classpath and it should work fine. 总之,只需指定类路径,它应该工作正常。 If not, look at what the error stream contains. 如果没有,请查看错误流包含的内容。

Note : You could have guessed the reason: the Javadoc specifies that readline() returns null if the end of the stream has been reached. 注意 :您可能已经猜到了原因:Javadoc指定readline()如果已到达流的末尾则返回null It was a clear indicator that the process was terminated early. 这是一个明确的指标,表明该过程提前终止。

BufferedReader#readLine will return null when it reaches the end of the stream. BufferedReader#readLine在到达流的末尾时将返回null

Because you're basically ignoring this exit indicator and looping in an infinite loop, all you get is null . 因为你基本上忽略了这个退出指示符并在无限循环中循环,所以你得到的只是null

The likely cause is because the process has output some error information to the error stream, which you are not reading... 可能的原因是因为该进程已向错误流输出一些错误信息,您没有阅读...

You should try using ProcessBuilder instead, which allows you to, amongst other things, redirect the error stream into the input stream 您应该尝试使用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- This will work if java.exe is your path, otherwise you will need to provide the full path to the executable as you already have done in your example ;) ps-如果java.exe是你的路径,这将有效,否则你将需要提供可执行文件的完整路径,就像你在示例中所做的那样;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM