2011-10-03 68 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

相关问题