在Java中获取命令提示输出到字符串

我需要一个java方法来读取命令提示输出并将其存储到String中以便读入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. 将这些查询存储在* .bat文件中

我不确定的唯一部分是第2步! 我可以很容易地做其他事情。 我已经阅读了很多关于OutputStreams的内容,但我似乎无法理解它是如何工作的。 我真的只需要输出一个字符串,我可以正则表达式来获取我需要的东西。 以下是我需要输入的内容以及我需要从输出中删除的内容的屏幕截图:

输入HandBrakeCLI:

在此处输入图像描述

要扫描的输出:

在此处输入图像描述

首先,您需要一种非阻塞方式来从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); } 

这几乎是我在需要Runtime.exec() Java时使用的锅炉板。

更高级的方法是使用FutureTaskCallable或至少Runnable而不是直接扩展Thread ,这不是最佳实践。

注意:

@Nonnull注释位于JSR305库中。 如果您正在使用Maven,并且您使用Maven不是您,只需将此依赖项添加到您的pom.xml

  com.google.code.findbugs jsr305 1.3.9  

这个完整的Java程序示例在命令行上运行命令’dir’(目录列表),并将结果拉入String并将其打印在控制台上。

 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  . 07/05/2012 01:06 PM  .. 06/05/2012 11:11 AM 301 .classpath 06/05/2012 11:11 AM 384 .project 06/05/2012 11:11 AM  .settings 07/05/2012 01:42 PM  bin 06/05/2012 11:11 AM  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 

假设您使用Runtime.exec()启动外部进程,为您提供Process对象,该对象上有三个相关方法: getOutputStream()getInputStream()getErrorStream()

我觉得很容易对这些感到困惑 – 你可能认为你想看到进程的输出,因此你想要的是“输出流”。 但是你需要记住的是,这些对象的命名来自Java代码的角度 – 一个OutputStream用于Java将输出写入,而InputStream用于Java来读取输入。 从Java的角度来看,外部进程的输出是输入。

因此,您将使用getInputStream()并在其返回的InputStream上调用适当的方法来读取输出。 您还可能希望使用getErrorStream()来确保您没有遗漏任何内容,因为它被写入标准错误。