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

发布于 2024-12-07 16:25:28 字数 2334 浏览 2 评论 0原文

我需要一个 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 正在 cmd 窗口下运行,而该窗口正在我的 IDE 下运行。所有这些都是有道理的,但 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 的输入:

在此处输入图像描述

扫描输出:

在此处输入图像描述

I need a java method that will read command prompt output and store it into a String to be read into 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. 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. 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.

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?
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. 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.

  2. Scan each folder using the HandBrakeCLI and store the output to a string.

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

  5. Store these queries in a *.bat file

The only part I'm not sure about is step 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. 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:

enter image description here

Output to scan:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾城泪 2024-12-14 16:25:28

这个完整的 Java 程序示例在命令行上运行命令“dir”(目录列表),并将结果提取到字符串中并将其打印在控制台上。

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

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.

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

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
一片旧的回忆 2024-12-14 16:25:28

首先,您需要一种非阻塞方式来读取 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>

First you need a non-blocking way to read from Standard.out and Standard.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 OutputStreamobjects.

    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.

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.

NOTE:

The @Nonnull annotations are in the JSR305 library. If you are using Maven, and you are using Maven aren't you, just add this dependency to your pom.xml.

<dependency>
  <groupId>com.google.code.findbugs</groupId>
  <artifactId>jsr305</artifactId>
  <version>1.3.9</version>
</dependency>
夜声 2024-12-14 16:25:28

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

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

因此,您可以使用 getInputStream() 并在其返回的 InputStream 上调用适当的方法来读取输出。您可能还需要使用 getErrorStream() 来确保您不会丢失任何内容,因为它被写入标准错误。

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

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. The output of your external process is, from Java's perspective, input.

So you would use getInputStream() and call appropriate methods on the InputStream returned by it to read the output. You also may want to use getErrorStream() to ensure that you are not missing anything because it is written to standard error.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文