2012-02-06 162 views
0

所以我正在编写一个程序来从Java运行命令行进程。这需要在Windows和Linux上运行;尽管我目前正在Windows 7上进行测试。我还应该提到,#之后的任何内容都被视为评论。就这样,这里是我的代码:使用来自Java的命令行 - 超时过程花费太长时间

import java.io.*; 
import java.util.*; 

public class myShell 
{ 
    public static void main(String[] args) 
    { 
     Runtime runtime = Runtime.getRuntime(); 
     Process process; 
     Scanner keyboard = new Scanner(System.in); 
     String userInput = ""; 
     String osName = System.getProperty("os.name"); 
     BufferedReader brStdOut = null; 
     String stdOut; 
     String stdOutNextLine; 
     BufferedReader brErrorStream = null; 
     String errorStream; 
     String errorStreamNextLine; 

     while(userInput.compareToIgnoreCase("exit") != 0) 
     { 
      System.out.println(); 
      System.out.print("??"); 

      userInput = keyboard.nextLine(); 

      int indexOfPound = userInput.indexOf('#'); 
      if(indexOfPound == 0) 
      { 
       userInput = ""; 
      } 
      else if(indexOfPound > 0) 
      { 
       userInput = userInput.substring(0, indexOfPound); 
      } 
      userInput = userInput.trim(); 

      try 
      { 
       if(osName.contains("Windows")) 
       { 
        process = runtime.exec("cmd /c " + userInput); 
       } 
       else 
       { 
        process = runtime.exec(userInput); 
       } 

       brStdOut = new BufferedReader(new InputStreamReader(
          process.getInputStream())); 
       brErrorStream = new BufferedReader(new InputStreamReader(
           process.getErrorStream())); 

       stdOut = ""; 
       errorStream = ""; 
       boolean firstStdOut = true; 
       boolean firstErrorStream = true; 
       long time = System.currentTimeMillis(); 

       while(((stdOutNextLine = brStdOut.readLine()) != null) && 
         ((System.currentTimeMillis() - time) < 5000)) 
       { 
        if(firstStdOut) 
        { 
         stdOut = stdOutNextLine; 
         firstStdOut = false; 
        } 
        else 
        { 
         stdOut = stdOut + "\n" + stdOutNextLine; 
        } 
       } 
       time = System.currentTimeMillis(); 
       while(((errorStreamNextLine = brErrorStream.readLine()) != null) 
         && ((System.currentTimeMillis() - time) < 5000)) 
       { 
        if(firstErrorStream) 
        { 
         errorStream = errorStreamNextLine; 
         firstErrorStream = false; 
        } 
        else 
        { 
         errorStream = errorStream + "\n" + errorStreamNextLine; 
        } 
       } 
       System.out.println(stdOut + errorStream); 
      } 
      catch(Exception e) 
      { 
       System.out.println("Error executing: " + userInput); 
       System.out.println(e.getMessage()); 
      } 
      try 
      { 
       brStdOut.close(); 
      } 
      catch(Exception e) 
      { 
      } 
      try 
      { 
       brErrorStream.close(); 
      } 
      catch(Exception e) 
      { 
      } 
     } 
     System.exit(0); 
    } 
} 

所以,我遇到的问题是,当我运行像它在命令行,将要求进一步的用户输入日期的命令。目前,我只想暂停这些类型的命令,并获取所有打印到超时过程的时间。

所以,如果在命令行日期会返回2行然后等待用户输入,我只想让我的程序打印这2行然后继续前进。 问题是,就像写入的那样,在while循环中从命令行获取输出的超时时间似乎没有任何作用,程序运行完全相同,有或没有(System.currentTimeMillis() - time)< 5000限定符。我也试着写while循环为:

while((stdOutNextLine = brStdOut.readLine()) != null) 
{ 
    if(firstStdOut) 
    { 
     stdOut = stdOutNextLine; 
     firstStdOut = false; 
    } 
    else 
    { 
     stdOut = stdOut + "\n" + stdOutNextLine; 
    } 
    if((System.currentTimeMillis() - time) > 5000) 
    { 
     throw new TimeoutException(); 
    } 
} 

,然后捕捉TimeoutException异常从那里与字符串的工作,但也似乎没有实际超时的过程。

还有其他想法吗?

谢谢!

回答

0

我建议您阅读问题here。用ProcessBuilder替换Process会更好。在调用外部命令时,还请阅读article以了解一些常见陷阱。

编辑: 问题是,readline方法被阻止,所以你的超时条件代码永远不会到达。您不能对Java流使用超时,除非您使用NIO。一种方法是在主线程发生超时时产生一个线程读取并杀死它。

+0

虽然这两种方法都有助于解决我之前使用此代码的问题,但他们实际上并未解决如何强制超时,这是我感兴趣的。谢谢。 – 2012-02-06 07:17:46

+0

第二个想法完美运作。谢谢。 – 2012-02-06 09:15:39

相关问题