2013-06-24 67 views
2

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

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

在代码中没有循环来重复'dir'ing。你使用'线'为什么?它似乎只是简单阅读,但没有在任何地方使用。 – allprog

回答

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项目。

+0

那它应该是什么? – user903772

+1

直到有更多的输入时,总会有'readLine()'阻塞的危险。 –

+0

@MarkoTopolnik就我个人而言,我会使用线程方法,但正如您所写,“...这是Java中的一个痛点......” –

2

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

具体而言,readLine()会阻塞,直到有整行被读取,或者直到底层流被关闭。

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

您也可以使用ProcessBuilder,特别是其redirectOutput方法与参数值INHERIT,使子继承你的主要过程的stdout。在这种情况下,您将没有机会分析Java中的子进程输出。

+1

+1 [新ProcessBuilder](http:// docs。 oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html) – linski