我有以下类文件。这将启动命令提示符并打印响应。奇怪的是在第一次打印之后,即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);
}
}
}
答案 0 :(得分: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项目。
答案 1 :(得分:2)
您正尝试使用同步I / O操作从一个线程进行基本的异步工作。你的方法必将失败。
具体来说,readLine()
会阻塞,直到有一整行要读取,或直到基础流关闭为止。
你需要编写更多代码,包括线程,才能使其工作。这是Java的一个难点。
您还可以使用ProcessBuilder
,尤其是redirectOutput
方法,使用参数值INHERIT
,以使子流程继承主进程的stdout
。在这种情况下,您将无法用Java分析子进程的输出。