命令在cmd上工作但在java代码中没有

时间:2013-12-27 20:56:21

标签: java command-line processbuilder

我正在使用mkvmerge将avi文件和ass文件合并到mkv文件中。 我当前有可执行文件和java文件的目录位于名为auto-mkvmerge的文件夹中。 当我在命令行中使用以下内容时,它正常工作,mkvmerge.exe -o ../auto-done/098.mkv ../auto-vid/098.avi ../auto-sub/098.ass我输出正确。 当我运行我的java代码时,它不起作用,并给我一个错误。

我的java代码。 Main.java

import java.io.*;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        File vidDir = new File(args[0]);
        File subDir = new File(args[1]);
        File outDir = new File(args[2]);

        String[] vids = vidDir.list();
        String[] subs = subDir.list();

        for(int i = 0; i < vids.length; i++) {
            int r = mergeAviAndAss(vids[i], subs[i], args[2]);
        }
    }

    private static int mergeAviAndAss(String aviFileName, String assFileName, String doneDir) {
        try {
            ProcessBuilder pb = new ProcessBuilder("mkvmerge.exe", "-o", doneDir + "/" + aviFileName.substring(0, aviFileName.length() - 4) + ".mkv", "\"" + aviFileName + "\"", "\"" + assFileName + "\"");
            Process p = pb.start();

            InputStream inputStream = p.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

            String line;
            while((line = br.readLine()) != null)
                System.out.println(line);

            return p.waitFor();
        } catch(IOException e) {
            e.printStackTrace();
        } catch(InterruptedException e) {
            e.printStackTrace();
        }

        return -1;
    }
}

当我使用以下行执行它时(在编译我的java代码之后):java Main ../auto-vid ../auto-sub ../auto-done > log.txt

mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00

Error: The file '098.avi' could not be opened for reading: open file error.

mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00

Error: The file '099.avi' could not be opened for reading: open file error.

mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00

Error: The file '100.avi' could not be opened for reading: open file error.

mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00

Error: The file '101.avi' could not be opened for reading: open file error.

mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00

Error: The file '102.avi' could not be opened for reading: open file error.

mkvmerge v6.6.0 ('The Edge Of The In Between') built on Dec  1 2013 17:55:00

Error: The file '103.avi' could not be opened for reading: open file error.

我的代码或我编写代码的方式有问题,因为如果我在命令行输入代码时它正常工作,它应该在我的java代码中工作。

3 个答案:

答案 0 :(得分:0)

我认为您可以使用Runtime.exec(java.lang.String[])并在Windows上使用Runtime.getRuntime().exec("cmd \c here goes your command")以使用指定的命令启动其控制台。

编辑:要运行所需的命令,请使用Runtime.getRuntime().exec("here goes your command")

答案 1 :(得分:0)

这是一个路径问题。你可以:

  • 运行java程序,传递视频文件的绝对路径:java Main c:\ pathtovideo1 \ video1.mvk c:\ pathtovideo2.avi ...
  • 转到所有视频所在的路径,然后执行java c:\ pathtomain \ Main video1.mvk video2.avi ...
  • 最后,您可以在java中指定更复杂的代码来处理路径(为视频附加固定路径等)。

如果这个选项有效,你可以知道还会有一个相对路径可以工作,概率为java Main ../auto-done/098.mkv ../auto-done/098.avi ...

答案 2 :(得分:0)

这是由techurbana指出的路径问题。

您需要在启动流程之前通过调用流程构建器的.directory(String)方法来设置流程上的工作目录。您需要为其提供应用程序的根目录。

您可以通过以下方式获取JAVA可执行文件的当前工作目录(可能是您存储mkvmerg.exe的位置):

 File dir = new File("");
 dir.getAbsolutePath();

如果您的mkvmerg.exe实用程序在您的系统中有一个类路径条目(无论如何在Windows上),您应该能够从任何目录运行mkvmerg.exe。

然后,如果您希望mkvmerge在某个子文件夹中处理文件,请执行FolderA:

 File subDir = new File(dir, "FolderA");
 subDir.getAbsolutePath();

尝试在运行时打印出用于控制台的所有路径,以验证文件和可执行文件的路径是否正确,并且调试应该很快。

请查看以下管理路径的示例。它只是用记事本打开当前目录中的文件,但几乎就是你想要做的。要运行它,请将一些路径作为参数传递给main()。

编辑 - 我刚刚意识到我从未真正使用传递给应用程序的路径,只能在java可执行文件的当前目录中查找第一个文件,但是你明白了。

 import java.io.BufferedReader;
 import java.io.File;
 import java.io.InputStream;
 import java.io.InputStreamReader;

 public class MainTest {

public static void main(String[] args) {
    // passes in a directory

    if (args.length > 0) {
        doSomethingWithCMD(args[0]);
    }
}

public static void doSomethingWithCMD(String filesDir) {


    try {
        File currDir = new File("");
        // this is a bit weird, but listFiles didnt return anything without
        // this next line.
        currDir = new File(currDir.getAbsolutePath());
        System.out.println(currDir.getAbsolutePath());

        // build our command with a string builder
        StringBuilder sb = new StringBuilder();

        // get the list of files
        File[] files = currDir.listFiles();

        // if there are no files this will be null so check first
        if (!(files == null)) {
            for (File f : files) {
                if (f.isFile()) {
                    sb.append("notepad ");
                    sb.append("\"" + f.getAbsolutePath());
                    sb.append("\"");
                    break;
                }
            }
        }
                    // create our process builder
        // first with no working dir & absolute paths
        ProcessBuilder pb = new ProcessBuilder(sb.toString());
        Process p = pb.start();

        InputStream inputStream = p.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(
                inputStream));

        String line;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        // cleanup
        try {
            inputStream.close();
        }
        catch (Exception ignore) {

        }
        try {
            br.close();
        }
        catch (Exception ignore) {

        }

        sb = new StringBuilder();
        // now we rebuild our command using relative paths instead of
        // absolute ones
        if (!(files == null)) {
            for (File f : files) {
                if (f.isFile()) {
                    sb.append("notepad ");
                    sb.append("\"" + f.getName());
                    sb.append("\"");
                    break;
                }
            }
        }

        pb = new ProcessBuilder(sb.toString());
                    //set the working directory
        pb.directory(currDir);
        p = pb.start();

        inputStream = p.getInputStream();
        br = new BufferedReader(new InputStreamReader(inputStream));

        line = null;
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }

    }
    catch (Exception e) {
        e.printStackTrace();
    }
}
 }