简体   繁体   English

在cmd上运行的命令但在Java代码中不起作用

[英]Command working on cmd but not in java code

I am using mkvmerge to merge an avi file and ass file into an mkv file. 我正在使用mkvmerge将avi文件和ass文件合并为mkv文件。 My current directory where I have the executable file and java file is in a folder called auto-mkvmerge . 我当前具有可执行文件和Java文件的目录位于一个名为auto-mkvmerge的文件夹中。 When I use the following in command-line it works normally, mkvmerge.exe -o ../auto-done/098.mkv ../auto-vid/098.avi ../auto-sub/098.ass I get the output correct. 当我在命令行中使用以下命令时,它可以正常工作,我得到了mkvmerge.exe -o ../auto-done/098.mkv ../auto-vid/098.avi ../auto-sub/098.ass输出正确。 When I run my java code, it does not work, and gives me an error. 当我运行Java代码时,它不起作用,并给我一个错误。

My java code. 我的Java代码。 Main.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;
    }
}

And when I execute it using the following line (after compiling my java code): java Main ../auto-vid ../auto-sub ../auto-done > log.txt 当我使用以下行(在编译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.

Is there something wrong with my code, or the way I've written it, because if it works normally when I type it in command-line it should be working in my java code. 我的代码或编写方式是否有问题,因为如果在命令行中键入它时它可以正常工作,则它应该可以在我的Java代码中工作。

I think you can use Runtime.exec(java.lang.String[]) and use Runtime.getRuntime().exec("cmd \\c here goes your command") on Windows to launch its console with a specified command. 我认为您可以在Windows上使用Runtime.exec(java.lang.String[])并使用Runtime.getRuntime().exec("cmd \\c here goes your command")以指定的命令启动其控制台。

EDIT: to just run the needed command, use Runtime.getRuntime().exec("here goes your command") 编辑:仅运行所需的命令,请使用Runtime.getRuntime().exec("here goes your command")

It's a path problem. 这是路径问题。 You can: 您可以:

  • Run your java program passing the absolute paths of the video files: java Main c:\\pathtovideo1\\video1.mvk c:\\pathtovideo2.avi ... 运行传递视频文件绝对路径的java程序:java Main c:\\ pathtovideo1 \\ video1.mvk c:\\ pathtovideo2.avi ...
  • Go to the path where all the videos are, and execute java c:\\pathtomain\\Main video1.mvk video2.avi ... 转到所有视频所在的路径,然后执行java c:\\ pathtomain \\ Main video1.mvk video2.avi ...
  • Finally, you can especify more complex code in the java to deal with paths (attach a fixed path for the videos, etc.) 最后,您可以在Java中指定更复杂的代码来处理路径(为视频附加固定路径等)。

If this options work, you can figure out that there will also be a relative path that will work, probabilly java Main ../auto-done/098.mkv ../auto-done/098.avi ... 如果此选项有效,您可以弄清楚也将有一条相对路径可以使用,可能是java Main ../auto-done/098.mkv ../auto-done/098.avi ...

This is a problem with paths as pointed out by techurbana. 正如Techurbana指出的,这是路径问题。

You need to set the working directory on your process by invoking the .directory(String) method of the process builder before starting the process. 您需要通过在启动流程之前调用流程构建器的.directory(String)方法来在流程上设置工作目录。 You need to give it the root directory of the application. 您需要为其提供应用程序的根目录。

You can get the current working directory of the JAVA executable (may or may not be where you store your mkvmerg.exe) by doing a: 您可以通过执行以下操作来获取JAVA可执行文件的当前工作目录(可能存储mkvmerg.exe,也可能不是该目录):

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

If your mkvmerg.exe utility has a class path entry in your system (on windows anyway) you should be able to run mkvmerg.exe from any directory. 如果mkvmerg.exe实用程序在系统中(无论如何在Windows上)都具有类路径条目,则应该可以从任何目录运行mkvmerg.exe。

Then if you have the files you wish mkvmerge to work on in some sub folder say FolderA you do: 然后,如果您希望mkvmerge在某些文件夹中工作,例如FolderA,则可以执行以下操作:

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

Just try printing out all the paths you are using to console during runtime to verify that the paths to the files, and to the executables are correct, and debugging should be a snap. 只需尝试打印出您在运行时用于控制台的所有路径,以验证文件和可执行文件的路径是否正确,调试应该很容易。

Please review the example of managing paths below. 请在下面查看管理路径的示例。 It just opens up files in the current directory with notepad, but is pretty much exactly what you want to do. 它只是使用记事本打开当前目录中的文件,但几乎完全是您想要执行的操作。 To run this, pass some path as an argument to main(). 要运行此命令,请将一些路径作为参数传递给main()。

EDIT - I just realized that I never actually make use of the path passed into the application, and only ever look for the first file in the current directory of the java executable, but you get the point. 编辑-我只是意识到我从来没有真正利用过传递到应用程序中的路径,只曾经在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();
    }
}
 }

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM