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

ken*_*dds 8 java outputstream tostring command-prompt

我需要一个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()
Run Code Online (Sandbox Code Playgroud)

我认为问题是当我尝试将查询更改为将执行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'
Run Code Online (Sandbox Code Playgroud)

哦,顺便说一句,当我在常规命令提示符下运行该查询时,它完全按我想要的那样,给我所有我迫切渴望的输出!

这是原始问题(我不确定如何重新提交问题):

我一直在寻找各处,无法弄清楚这一点.我不确定我发现的东西与我想做的事情有关.我还没有很多代码,因此在这里放置代码并不会做太多事情,我认为这应该很简单,所以我将在这里给出一些截图.所以这是我的任务:

  1. 扫描文件夹,其中包含翻录的DVD文件夹(带有VOB文件的Video_TS文件夹等),并将这些文件夹名称存储为DVD的标题.

  2. 使用HandBrakeCLI扫描每个文件夹并将输出存储到字符串.

  3. 正则表达式字符串,以标识每个标题,章节和语言.

  4. 生成查询以回馈HandBrakeCLI,对每张DVD的每个标题中的每一章中的每种语言进行批量编码(您可以看到我为什么要自动执行此操作!)

  5. 将这些查询存储在*.bat文件中

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

输入HandBrakeCLI:

在此输入图像描述

要扫描的输出:

在此输入图像描述

Eri*_*ski 6

这个完整的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(){   }
}
Run Code Online (Sandbox Code Playgroud)

在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
Run Code Online (Sandbox Code Playgroud)


小智 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,你需要这个类扎入各自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);
    }
Run Code Online (Sandbox Code Playgroud)

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

更先进的方法是使用FutureTask和/ Callable或至少Runnable而不是直接扩展Thread,这不是最佳实践.

注意:

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

<dependency>
  <groupId>com.google.code.findbugs</groupId>
  <artifactId>jsr305</artifactId>
  <version>1.3.9</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)