简体   繁体   English

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

[英]Get Command Prompt Output to String In Java

I need a java method that will read command prompt output and store it into a String to be read into Java. 我需要一个java方法,它将读取命令提示输出并将其存储到String中以便读入Java。

This is what I have so far but isn't working right. 这是我到目前为止所做的,但是工作不正常。

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()

I think the problem is when I try to change the query to be a command which will execute HandBrakeCLI.exe. 我认为问题是当我尝试将查询更改为将执行HandBrakeCLI.exe的命令时。 Looking at my system when the program is running (but seems to have paused), it shows me that HandBrakeCLI.exe is running under a cmd window which is being run under my IDE. 在程序运行时查看我的系统(但似乎已暂停),它向我显示HandBrakeCLI.exe正在我的IDE下运行的cmd窗口下运行。 All that makes sense, but the HandBrakeCLI.exe doesn't exit, so I'm guessing that's why I can't read the output as input to my program. 所有这一切都有道理,但HandBrakeCLI.exe没有退出,所以我猜这就是为什么我无法将输出读作我程序的输入。

So, after that background. 所以,在那个背景之后。 My big question is this: How do I get HandBrakeCLI.exe to close after it's finished with my query so I can get its output? 我的一个大问题是:在完成查询后如何让HandBrakeCLI.exe关闭以便我可以得到它的输出? Just for extra info, the only difference between the method above and the scan DVD method I have for HandBrakeCLI is the query variable is different. 仅仅为了额外的信息,上面的方法与我对HandBrakeCLI的扫描DVD方法的唯一区别是查询变量是不同的。 Like this example: 像这个例子:

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'

Oh, and by the way, when I run that query in a regular command prompt, it does exactly what I want it to, giving me all the output I desperately desire! 哦,顺便说一句,当我在常规命令提示符下运行该查询时,它完全按我想要的那样,给我所有我迫切渴望的输出!

Here's the original problem (I'm not sure how to resubmit a question): 这是原始问题(我不确定如何重新提交问题):

I've been looking everywhere and can't figure this out. 我一直在寻找各处,无法弄清楚这一点。 I'm not sure what I've found is even relevant to what I want to do. 我不确定我发现的东西与我想做的事情有关。 I don't have a whole lot of code for it yet, so it wont do much to put code here and I think this should be pretty simple, so I'm going to give some screenshots here. 我还没有很多代码,所以在这里放置代码并没有太大的作用,我认为这应该很简单,所以我将在这里给出一些截图。 So here's my task: 所以这是我的任务:

  1. Scan folder which is full of ripped DVD folders (Video_TS folders with VOB files etc.) and store these folder names as the title of the DVD. 扫描文件夹,其中包含翻录的DVD文件夹(带有VOB文件的Video_TS文件夹等),并将这些文件夹名称存储为DVD的标题。

  2. Scan each folder using the HandBrakeCLI and store the output to a string. 使用HandBrakeCLI扫描每个文件夹并将输出存储到字符串。

  3. Regex the string to identify each title, chapter, and language. 正则表达式字符串,以标识每个标题,章节和语言。

  4. Generate queries to give back to HandBrakeCLI to bulk encode each language in each chapter in each title for each DVD (you can see why I want to automate this!) 生成查询以回馈HandBrakeCLI,对每张DVD的每个标题中的每一章中的每种语言进行批量编码(您可以看到我为什么要自动执行此操作!)

  5. Store these queries in a *.bat file 将这些查询存储在* .bat文件中

The only part I'm not sure about is step 2! 我不确定的唯一部分是第2步! I can do everything else pretty easily. 我可以很容易地做其他事情。 I've read a lot about OutputStreams, but I just can't seem to understand how it works. 我已经阅读了很多关于OutputStreams的内容,但我似乎无法理解它是如何工作的。 I really just need to get the output to a string which I can regex to get the stuff I need. 我真的只需要输出一个字符串,我可以正则表达式来获取我需要的东西。 Here are the screenshots of what I need to input and what I need to strip from the output: 以下是我需要输入的内容以及我需要从输出中删除的内容的屏幕截图:

Input to HandBrakeCLI: 输入HandBrakeCLI:

在此输入图像描述

Output to scan: 要扫描的输出:

在此输入图像描述

This full Java program example runs the command 'dir' (directory listing) on the command line and pulls the result into a String and prints it on the console. 这个完整的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(){   }
}

On Windows, this is the result I get 在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

First you need a non-blocking way to read from Standard.out and Standard.err 首先,您需要一种非阻塞方式来从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();
    }
}

Then you need to tie this class into the respective InputStream and OutputStream objects. 然后,您需要将此类绑定到相应的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);
    }

This is pretty much the boiler plate I use when I need to Runtime.exec() anything in Java. 这几乎是我在需要Runtime.exec() Java时使用的锅炉板。

A more advanced way would be to use FutureTask and Callable or at least Runnable rather than directly extending Thread which isn't the best practice. 更高级的方法是使用FutureTaskCallable或至少Runnable而不是直接扩展Thread ,这不是最佳实践。

NOTE: 注意:

The @Nonnull annotations are in the JSR305 library. @Nonnull注释位于JSR305库中。 If you are using Maven, and you are using Maven aren't you, just add this dependency to your pom.xml . 如果您正在使用Maven,并且您使用Maven不是您,只需将此依赖项添加到您的pom.xml

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

Assuming you use Runtime.exec() to start your external process, giving you a Process object, there are three relevant methods on that object: getOutputStream() , getInputStream() , and getErrorStream() . 假设您使用Runtime.exec()启动外部进程,为您提供Process对象,该对象上有三个相关方法: getOutputStream()getInputStream()getErrorStream()

I think it is easy to get confused about these -- you are probably thinking that you want to see the process's output, so therefore an "output stream" is what you want. 我认为很容易对这些感到困惑 - 你可能认为你想看到进程的输出,因此你想要的是“输出流”。 But the thing you need to remember is that the naming of these objects is from the Java code's perspective -- an OutputStream is for Java to write output to, while an InputStream is for Java to read input from. 但是你需要记住的是,这些对象的命名来自Java代码的角度 - 一个OutputStream用于Java写入输出,而InputStream用于Java来读取输入。 The output of your external process is, from Java's perspective, input. 从Java的角度来看,外部进程的输出是输入。

So you would use getInputStream() and call appropriate methods on the InputStream returned by it to read the output. 因此,您将使用getInputStream()并在其返回的InputStream上调用适当的方法来读取输出。 You also may want to use getErrorStream() to ensure that you are not missing anything because it is written to standard error. 您还可能希望使用getErrorStream()来确保您没有遗漏任何内容,因为它被写入标准错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在java中获取命令提示符输出? - How to get command prompt output in java? 输入命令并获取命令提示符完整输出到Java中的textarea - Give input command and Get Command Prompt complete Output to textarea In Java 如何在Java中将AT命令的输出转换为字符串? - How to get the output of AT command into a string in java? 使用java将输出写入命令提示符 - write output to command prompt using java 命令提示符和输出文件之间的Java拆分输出 - Java-split output between command prompt and output file 如何从句子中获取单词以存储在Java的命令提示符下的单独字符串中 - How to get words from sentence to be stored in separate string in command prompt in java 显示Java程序的输出并将其从命令提示符复制到文件中 - Displaying and copying output of a java program from command prompt into a file 通过带有输入和输出文件的命令提示符运行Java程序 - Running Java program via Command Prompt with input and output files 在Windows中使用Java将命令提示符的输出重定向到文本文件 - redirecting output of command prompt to a text file using java in windows Java 项目的输出无法在 Windows 命令提示符下正确打印 ä 或 ö - Java project's output does not print ä or ö correctly in Windows command prompt
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM