2011-10-03 67 views
7

我需要一個java方法,它將讀取命令提示符輸出並將其存儲到要讀入Java的字符串中。獲取命令提示輸出到Java中的字符串

這是我迄今爲止,但沒有正確工作。

public void testGetOutput() { 
    System.out.println("\n\n****This is the testGetOutput Method!****"); 
    String s = null; 
    String query = "dir " + this.desktop; 
    try { 
     Runtime runtime = Runtime.getRuntime(); 
     InputStream input = runtime.exec("cmd /c " + query).getInputStream(); 
     BufferedInputStream buffer = new BufferedInputStream(input); 
     BufferedReader commandResult = new BufferedReader(new InputStreamReader(buffer)); 
     String line = ""; 
     try { 
      while ((line = commandResult.readLine()) != null) { 
       s += line + "\n"; 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     System.out.println(s); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
}//end testGetOutput() 

我認爲問題是當我嘗試將查詢更改爲將執行HandBrakeCLI.exe的命令。當程序運行時(但似乎已暫停)看着我的系統,它顯示出HandBrakeCLI.exe正在我的IDE下運行的cmd窗口下運行。所有這一切都有道理,但HandBrakeCLI.exe不會退出,所以我猜這就是爲什麼我無法讀取輸出作爲我的程序輸入。

所以,在那之後。我的大問題是:我的查詢完成後如何讓HandBrakeCLI.exe關閉,以便我可以得到它的輸出? 只是額外的信息,上面的方法和我爲HandBrakeCLI掃描DVD方法之間的唯一區別是查詢變量是不同的。像這樣的例子:

String query = "C:\Users\Kent\Desktop\HBCLI\HandBrakeCLI -t --scan -i "C:\Users\Kent\Desktop\General Conference DVDs\Sources\174th October 2004\DVD 1"; //this is actually a variable in the DVD object, but here's an example' 

哦,順便說一下,當我在一個普通命令提示符下運行該查詢,它正是我想要的它,讓我所有的輸出我拼命的願望!

這裏是原來的問題(我不知道如何重新提交問題):

我一直在到處找,不能想出解決辦法。我不確定我發現的內容甚至與我想要做的事情有關。我還沒有很多代碼,所以它不會做太多的代碼,我認爲這應該很簡單,所以我會在這裏給出一些截圖。因此,這裏是我的任務:

  1. 掃描文件夾裏面充滿翻錄DVD文件夾(與VOB文件等VIDEO_TS文件夾),並且這些文件夾名稱存儲爲DVD的標題。

  2. 使用HandBrakeCLI掃描每個文件夾並將輸出存儲爲字符串。

  3. 將字符串正確表示以標識每個標題,章節和語言。

  4. 生成查詢退給HandBrakeCLI批量編碼在每個標題爲每個DVD每章每一種語言(你可以看到我爲什麼要自動執行此!)

  5. 存儲這些查詢的*。蝙蝠文件

我不確定的唯一部分是第2步!我可以很容易地做其他事情。我已經閱讀了很多關於OutputStreams的內容,但我似乎無法理解它是如何工作的。我真的只需要得到輸出到一個字符串,我可以正則表達式來獲得我需要的東西。下面是我需要輸入什麼,什麼我需要從輸出到剝離截圖:

輸入到HandBrakeCLI:

enter image description here

輸出掃描:

enter image description here

回答

5

首先你需要一個無阻塞的方式來讀取Standard.outStandard.err

private class ProcessResultReader extends Thread 
{ 
    final InputStream is; 
    final String type; 
    final StringBuilder sb; 

    ProcessResultReader(@Nonnull final InputStream is, @Nonnull String type) 
    { 
     this.is = is; 
     this.type = type; 
     this.sb = new StringBuilder(); 
    } 

    public void run() 
    { 
     try 
     { 
      final InputStreamReader isr = new InputStreamReader(is); 
      final BufferedReader br = new BufferedReader(isr); 
      String line = null; 
      while ((line = br.readLine()) != null) 
      { 
       this.sb.append(line).append("\n"); 
      } 
     } 
     catch (final IOException ioe) 
     { 
      System.err.println(ioe.getMessage()); 
      throw new RuntimeException(ioe); 
     } 
    } 

    @Override 
    public String toString() 
    { 
     return this.sb.toString(); 
    } 
} 

然後,你需要這個類扎入相應的InputStreamOutputStream對象。

try 
    { 
     final Process p = Runtime.getRuntime().exec(String.format("cmd /c %s", query)); 
     final ProcessResultReader stderr = new ProcessResultReader(p.getErrorStream(), "STDERR"); 
     final ProcessResultReader stdout = new ProcessResultReader(p.getInputStream(), "STDOUT"); 
     stderr.start(); 
     stdout.start(); 
     final int exitValue = p.waitFor(); 
     if (exitValue == 0) 
     { 
      System.out.print(stdout.toString()); 
     } 
     else 
     { 
      System.err.print(stderr.toString()); 
     } 
    } 
    catch (final IOException e) 
    { 
     throw new RuntimeException(e); 
    } 
    catch (final InterruptedException e) 
    { 
     throw new RuntimeException(e); 
    } 

這是相當多的鍋爐板,當我需要在Java中Runtime.exec()什麼我使用。

更高級的方法是使用FutureTaskCallable或至少Runnable而不是直接擴展Thread,這不是最佳實踐。

注:

@Nonnull註釋是在JSR305庫。如果您使用的是Maven,並且您使用的是Maven,那麼只需將此依賴項添加到您的pom.xml

<dependency> 
    <groupId>com.google.code.findbugs</groupId> 
    <artifactId>jsr305</artifactId> 
    <version>1.3.9</version> 
</dependency> 
+0

Jarrod,感謝您的快速響應!我會盡力實現這一點,並讓你知道它是怎麼回事! – kentcdodds

+0

完美!我不完全確定它是如何工作的。但是我會稍微查看一下以找出答案。但是,它的功能就像一個魅力!現在我只需要將所有這些東西進行正則表達式!無論如何,謝謝你的幫助!哦,我不確定Maven是什麼。我的IDE是Netbeans。我不需要添加的東西。再次感謝! – kentcdodds

1

假設您使用Runtime.exec()開始外部過程,併爲您提供Process對象,則該對象上有三種相關方法:getOutputStream()getInputStream()getErrorStream()

我覺得很容易混淆這些 - 你可能認爲你想看到進程的輸出,所以「輸出流」就是你想要的。但是你需要記住的是,這些對象的命名是從Java代碼的角度來看的 - 一個OutputStream用於Java寫輸出,而一個InputStream用於Java讀輸入。從Java的角度來看,外部流程的輸出是輸入。

因此,您將使用getInputStream()並在其返回的InputStream上調用適當的方法來讀取輸出。您也可能想要使用getErrorStream()以確保您不會錯過任何內容,因爲它被寫入標準錯誤。

+0

感謝澄清!這有點令人困惑。我現在面臨的問題是不打印查詢結果(如我的第二張截圖所示),而是打印查詢本身。代碼中有太多內容需要添加到評論中,因此以下鏈接指向collabedit文檔:http:// collabedit。com/5r384 – kentcdodds

+0

我認爲一個問題是'exec()'需要一個實際的可執行文件 - 批處理文件不是可執行程序,它是由Windows shell執行的一系列命令。請參閱http://stackoverflow.com/questions/615948/how-do-i-run-a-batch-file-from-my-java-application。 –

+0

我們正在接近!所以現在我的問題是我的緩衝讀者對象爲null。我不知道爲什麼。我更新了collabedit文檔中的代碼。你會注意到我把println放在commandResult的周圍,因爲這是代碼暫停的地方,而commandResult.readLine()= null應該等於第一個輸入行(或者至少,這就是我正在尋找的)。再次感謝您的幫助! http://collabedit.com/5r384 – kentcdodds

5

這個完整的Java程序示例運行在命令行命令「目錄」(目錄列表),結果拉成字符串並將其打印在控制檯上。

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 

public class X { 
    public static void main(String[] args) { 
     try{ 
      String command = "dir"; 
      String s = get_commandline_results(command); 
      System.out.println(s); 
     } 
     catch(Exception e){ 
      e.printStackTrace(); 
     } 
     System.out.println("done"); 
    } 

    public static String get_commandline_results(String cmd) 
     throws IOException, InterruptedException, IllegalCommandException{ 

     //Do not remove the authorizedCommand method. Be prepared 
     //to lose your hard drive if you have not white-listed the 
     //commands that can run. 
     if (!authorizedCommand(cmd)) 
      throw new IllegalCommandException(); 

     String result = ""; 
     final Process p = Runtime.getRuntime(). 
      exec(String.format("cmd /c %s", cmd)); 
     final ProcessResultReader stderr = new ProcessResultReader(
       p.getErrorStream(), "STDERR"); 
     final ProcessResultReader stdout = new ProcessResultReader(
       p.getInputStream(), "STDOUT"); 
     stderr.start(); 
     stdout.start(); 
     final int exitValue = p.waitFor(); 
     if (exitValue == 0){ 
      result = stdout.toString(); 
     } 
     else{ 
      result = stderr.toString(); 
     } 
     return result; 
    } 
    public static boolean authorizedCommand(String cmd){ 
     //Do not allow any command to be run except for the ones 
     //that we have pre-approved here. This lessens the 
     //likelihood that fat fingers will wreck your computer. 
     if (cmd.equals("dir")) 
      return true; 
     //add the commands you want to authorize here. 

     return false; 
    } 
} 

class ProcessResultReader extends Thread{ 
    final InputStream is; 
    final String type; 
    final StringBuilder sb; 

    ProcessResultReader(final InputStream is, String type){ 
     this.is = is; 
     this.type = type; 
     this.sb = new StringBuilder(); 
    } 

    public void run() 
    { 
     try{ 
      final InputStreamReader isr = new InputStreamReader(is); 
      final BufferedReader br = new BufferedReader(isr); 
      String line = null; 
      while ((line = br.readLine()) != null) 
      { 
       this.sb.append(line).append("\n"); 
      } 
     } 
     catch (final IOException ioe) 
     { 
      System.err.println(ioe.getMessage()); 
      throw new RuntimeException(ioe); 
     } 
    } 
    @Override 
    public String toString() 
    { 
     return this.sb.toString(); 
    } 
} 
class IllegalCommandException extends Exception{ 
    private static final long serialVersionUID = 1L; 
    public IllegalCommandException(){ } 
} 

在Windows中,這是結果我得到

Directory of D:\projects\eric\eclipseworkspace\testing2 
07/05/2012 01:06 PM <DIR>   . 
07/05/2012 01:06 PM <DIR>   .. 
06/05/2012 11:11 AM    301 .classpath 
06/05/2012 11:11 AM    384 .project 
06/05/2012 11:11 AM <DIR>   .settings 
07/05/2012 01:42 PM <DIR>   bin 
06/05/2012 11:11 AM <DIR>   src 
07/05/2012 01:06 PM    2,285 usernames.txt 
       3 File(s)   2,970 bytes 
       5 Dir(s) 45,884,035,072 bytes free 

done 
+0

+1爲未來世代發佈另一種可行的解決方案。 – kentcdodds

相關問題