1

所以伙计们,我想执行一个可以在我的 Java 程序中的 cmd 上执行的命令。在做了一些研究之后,我想我找到了一种方法来做到这一点。但是,我的代码不起作用。

我的代码是

import java.io.*;

public class CmdTest {
    public static void main(String[] args) throws Exception {
        String[] command = {"ag","startTimes conf.js >> pro.txt"};
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.directory(new File("./test-java/"));
        Process p = builder.start();
    }
}

程序执行但不产生输出。我尝试使用其他命令,如“ls -a”,但仍然没有输出。

有人可以帮我调试这个或建议一个更好的方法吗?谢谢

编辑 1:我在 Mac 上执行此操作。如果这是调试所必需的

编辑 2:通常的 ls 和其他命令正在使用你们提供的解决方案。但是,我想在 Java 程序中使用 ag (the_silver_searcher) 命令。当我尝试这样做时,我收到以下错误 -

Exception in thread "main" java.io.IOException: Cannot run program "ag startTimes conf.js >> pro.txt": error=2, No such file or directory 
4

5 回答 5

1

虽然有ProcessBuilder,但我一直使用Runtime.getRuntime().exec("cmd");

进程运行时.exec(字符串)

它返回一个Process,您可以获取它的输入和输出流

即使您留在ProcessBuilder,您仍然应该可以访问Process.get<Input/Output/Error>Stream()

于 2017-10-13T17:25:05.313 回答
1

现有答案为您提供了有关如何在代码中解决问题的信息,但它们没有说明您的代码无法正常工作的原因。

当您在 shell 上执行程序时,shell 会在程序执行之前完成重要的处理。你的命令行

    String[] command = {"ag","startTimes conf.js >> pro.txt"};
    ProcessBuilder builder = new ProcessBuilder(command);

假设该命令ag使用单个参数运行startTimes conf.js >> pro.txt- 很可能不是您想要做的。让我们更进一步:如果你写了

    String[] command = {"ag","startTimes", "conf.js", ">>", "pro.txt"};
    ProcessBuilder builder = new ProcessBuilder(command);

?

这将假设该ag命令知道>>重定向其输出的参数 - 这就是 shell 发挥作用的地方:操作符是对 shell>>的指令,告诉如何处理来自进程的 stdout 的输出。该进程在由 shell 启动时,从不知道这种重定向,并且根本不知道目标文件名。ag>>

有了这些信息,只需使用任何其他答案中的代码示例。我不会将它们复制到我的中以进行适当的归属。

于 2017-10-18T07:20:55.190 回答
0

您需要通过打开进程的输入流来读取进程的输出:

try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())) {
    System.out.println(reader.readLine()); // process the output stream somehow
}

此外,您可能p.getErrorStream()会读取错误流(当然,您无法再区分输入来自哪个流,但它使阅读更容易。如果您不读取输入或错误流并且进程的缓冲区已满,则进程往往会暂停,直到缓冲区再次有足够的空间。redirectErrorStream(true)ProcessBuilder

于 2017-10-13T17:25:16.697 回答
0
//"ls" command runs under the "sh" on linux(cmd.exe on windows), so first arg is "sh"    
//second arg "-c" tells "sh" which exact command should be executed
//"ls" is actual command
//"startTimes" as I understand is a file or directory, it is arg for "ls" command
//"conf.js" is second arg for "ls" command
new ProcessBuilder("sh", "-c", "ls", "startTimes", "conf.js")
//set working dir for "sh" process"
            .directory(new File("./test-java/"))
//output will be written to "pro.txt" in working dir of "sh" process
            .redirectOutput(new File("./test-java/pro.txt"))
            .start();
于 2017-10-13T17:58:24.050 回答
0

您还可以添加

builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);

在将输出重定向到控制台的 start 方法之前。

于 2017-10-13T17:26:53.213 回答