命令在cmd上工作,但不在java代码中

命令在cmd上工作,但不在java代码中,java,command-line,processbuilder,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.*; impo

我正在使用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代码中工作。

我认为您可以在Windows上使用并使用
Runtime.getRuntime().exec(“cmd\c这里是您的命令”)
以指定的命令启动其控制台


编辑:要运行所需的命令,请使用
Runtime.getRuntime().exec(“这是您的命令”)
这是一个路径问题。你可以:

  • 运行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

这是techurbana指出的路径问题

在启动流程之前,需要通过调用process builder的.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();
    }
}
 }

“打开文件”错误是否意味着无法打开该文件,因为找不到该文件,或者因为该文件当前具有某种独占锁定?可能很傻,但你确定你没有在其他应用程序中打开该文件吗?是的,我检查了,我甚至打印了文件列表,以检查它们是否都有正确的名称和扩展名,并且我确保它们没有打开。你能试着将生成的字符串写入传递到process builder的标准输出吗,只是为了验证字符串没有问题?工作目录可能对可执行文件也很重要。尝试使用pb.directory(“此处包含文件的路径”)在process builder上设置工作目录;在启动该过程之前,我尝试将avi和ass文件与mkvmerge.exe和我的java文件放在同一个目录中,它正常工作第一个选项正常工作,但我希望能够指定包含文件的目录,而不是文件本身。我正在尝试您编写的第三个选项唯一有效的选项是将所有文件放在与exe文件和java类相同的目录中,因此这是我现在选择的选项。我尝试了将文件放在子文件夹中的方法,现在,当获取文件数组的长度时,我得到了一个NullPointerException。我像您一样添加了dir对象,并且在运行java类时,我编写了
java Main auto vid/auto sub/auto done/
 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();
    }
}
 }