Java Process Builder - 不能 运行 一个简单的程序
Java Process Builder - Cannot run a simple program
我有一个名为 darknet
的程序。这是一个由 Darknet.
编写的 C 程序
我想 运行 文件夹 Darknet
中的 darknet
程序,如下所示:
我打算 运行 darknet
使用 Java Process Builder,但是当我 运行 这段代码时我没有得到任何回应:
// Arguments
String darknetNamePath = darknet.getValue().getFilePath().replace("Darknet/", "./");
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/cameraSnap.png";
String thresholdFlag = "-thresh " + thresholds.getValue();
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(new File("Darknet")); // We need to stand inside the folder "Darknet"
String commandString = "detect " + configurationFlag + " " + weightsFlag + " " + imageFlag + " " + thresholdFlag;
System.out.println("darknetNamePath = " + darknetNamePath);
System.out.println("commandString = " + commandString);
processBuilder.command(darknetNamePath, commandString);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
这是我的输出。为什么它对我不起作用?
darknetNamePath = ./darknet
commandString = detect cfg/yolov2-tiny.cfg weights/yolov2-tiny.weights data/cameraSnap.png -thresh 0.8
Exited with error code : 0
但是当我通过终端调用 darknet
文件时,它就可以工作了。
./darknet detect cfg/yolov2-tiny.cfg weights/yolov2-tiny.weights data/cameraSnap.png -thresh 0.6
更新 2:
这是我的更新。
// Arguments
String darknetNamePath = darknet.getValue().getFile().getAbsolutePath();
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/cameraSnap.png";
String thresholdFlag = "-thresh " + thresholds.getValue();
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(darknetNamePath, "detect", configurationFlag, weightsFlag, imageFlag, thresholdFlag);
Process process = processBuilder.start();
if (process.getInputStream().read() == -1) {
System.out.println(darknetNamePath);
System.out.println("detect");
System.out.println(configurationFlag);
System.out.println(weightsFlag);
System.out.println(imageFlag);
System.out.println(thresholdFlag);
System.out.printf("ERROR!");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
输出:
/home/dell/Dokument/GitHub/Vaadin-DL4J-YOLO-Camera-Mail-Reporter/Vaadin-DL4J-YOLO-Camera-Mail-Reporter/Darknet/darknet
detect
cfg/yolov2-tiny.cfg
weights/yolov2-tiny.weights
data/cameraSnap.png
-thresh 0.3
ERROR!
Exited with error code : 0
更新 3:
这个有效:
// Arguments
String darkPath = darknet.getValue().getFilePath().replace("Darknet/", "./"); // We need to call ./darknet, not absolute path
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/camera.png";
String thresValue = String.valueOf(thresholds.getValue());
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(new File("Darknet")); // Important
processBuilder.command(darkPath, "detect", configurationFlag, weightsFlag, imageFlag, "-thresh", thresValue);
processBuilder.redirectErrorStream(true); // Important
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
您使用 ProcessBuilder
的方式不对。 command 方法将可执行文件和参数作为单独的字符串,而不是路径,然后是另一个包含实际命令及其所有参数的字符串。没有 shell 涉及对命令进行分词,因此您将所有不同的参数作为一个参数传递。
我没有暗网,所以这是一个使用 Unix echo
命令的简单命令:
import java.io.*;
public class ProcessBuilderTest {
public static void main(String[] args) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder();
String[] command = {"/bin/echo", "hello", "world"};
processBuilder.command(command);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("Exited with error code : " + exitCode);
}
}
当我 运行 这个时,我得到:
robert@saaz:~$ java ProcessBuilderTest.java
hello world
Exited with error code : 0
我不清楚为什么你的命令没有产生错误。如果我给出一个错误的命令(例如,“echo”后面的尾随 space),我会得到一个例外:
Exception in thread "main" java.io.IOException: Cannot run program "/bin/echo ": error=2, No such file or directory
这可能是 OS 具体的。或者,也许您有一些其他 darknet
可执行文件被拾取。
您的命令必须将所有参数分成单独的部分 - 包括 thresholdFlag
。检查可执行文件是否存在是个好主意。如果没有,您应该检查它的位置或修复您的 Path 变量以确保可以找到它:
File darkpath = new File(darknetNamePath);
String [] cmd = new String[] { darkpath.getAbsolutePath(), "detect", configurationFlag, weightsFlag, imageFlag, "-thresh", String.valueOf(thresholds.getValue()) };
System.out.println("Path: "+darkpath+ " exists="+darkpath.exists());
System.out.println("exec "+Arrays.toString(cmd));
processBuilder.command(cmd);
也值得处理 STDERR,最简单的方法是在调用之前重定向 STDERR=>STDOUT processBuilder.start()
processBuilder.redirectErrorStream(true);
如果您希望 Java 在不添加绝对路径前缀的情况下启动可执行文件,它需要位于以下目录之一:
System.out.println("PATH COMPONENTS FOR JAVA LAUNCH:");
Arrays.asList(System.getenv("PATH").split(File.pathSeparator)).forEach(System.out::println);
我有一个名为 darknet
的程序。这是一个由 Darknet.
我想 运行 文件夹 Darknet
中的 darknet
程序,如下所示:
我打算 运行 darknet
使用 Java Process Builder,但是当我 运行 这段代码时我没有得到任何回应:
// Arguments
String darknetNamePath = darknet.getValue().getFilePath().replace("Darknet/", "./");
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/cameraSnap.png";
String thresholdFlag = "-thresh " + thresholds.getValue();
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(new File("Darknet")); // We need to stand inside the folder "Darknet"
String commandString = "detect " + configurationFlag + " " + weightsFlag + " " + imageFlag + " " + thresholdFlag;
System.out.println("darknetNamePath = " + darknetNamePath);
System.out.println("commandString = " + commandString);
processBuilder.command(darknetNamePath, commandString);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
这是我的输出。为什么它对我不起作用?
darknetNamePath = ./darknet
commandString = detect cfg/yolov2-tiny.cfg weights/yolov2-tiny.weights data/cameraSnap.png -thresh 0.8
Exited with error code : 0
但是当我通过终端调用 darknet
文件时,它就可以工作了。
./darknet detect cfg/yolov2-tiny.cfg weights/yolov2-tiny.weights data/cameraSnap.png -thresh 0.6
更新 2:
这是我的更新。
// Arguments
String darknetNamePath = darknet.getValue().getFile().getAbsolutePath();
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/cameraSnap.png";
String thresholdFlag = "-thresh " + thresholds.getValue();
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.command(darknetNamePath, "detect", configurationFlag, weightsFlag, imageFlag, thresholdFlag);
Process process = processBuilder.start();
if (process.getInputStream().read() == -1) {
System.out.println(darknetNamePath);
System.out.println("detect");
System.out.println(configurationFlag);
System.out.println(weightsFlag);
System.out.println(imageFlag);
System.out.println(thresholdFlag);
System.out.printf("ERROR!");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
输出:
/home/dell/Dokument/GitHub/Vaadin-DL4J-YOLO-Camera-Mail-Reporter/Vaadin-DL4J-YOLO-Camera-Mail-Reporter/Darknet/darknet
detect
cfg/yolov2-tiny.cfg
weights/yolov2-tiny.weights
data/cameraSnap.png
-thresh 0.3
ERROR!
Exited with error code : 0
更新 3:
这个有效:
// Arguments
String darkPath = darknet.getValue().getFilePath().replace("Darknet/", "./"); // We need to call ./darknet, not absolute path
String configurationFlag = configuration.getValue().getFilePath().replace("Darknet/", "");
String weightsFlag = weights.getValue().getFilePath().replace("Darknet/", "");
String imageFlag = "data/camera.png";
String thresValue = String.valueOf(thresholds.getValue());
// Process builder
ProcessBuilder processBuilder = new ProcessBuilder();
processBuilder.directory(new File("Darknet")); // Important
processBuilder.command(darkPath, "detect", configurationFlag, weightsFlag, imageFlag, "-thresh", thresValue);
processBuilder.redirectErrorStream(true); // Important
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("\nExited with error code : " + exitCode);
您使用 ProcessBuilder
的方式不对。 command 方法将可执行文件和参数作为单独的字符串,而不是路径,然后是另一个包含实际命令及其所有参数的字符串。没有 shell 涉及对命令进行分词,因此您将所有不同的参数作为一个参数传递。
我没有暗网,所以这是一个使用 Unix echo
命令的简单命令:
import java.io.*;
public class ProcessBuilderTest {
public static void main(String[] args) throws Exception {
ProcessBuilder processBuilder = new ProcessBuilder();
String[] command = {"/bin/echo", "hello", "world"};
processBuilder.command(command);
Process process = processBuilder.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
int exitCode = process.waitFor();
System.out.println("Exited with error code : " + exitCode);
}
}
当我 运行 这个时,我得到:
robert@saaz:~$ java ProcessBuilderTest.java
hello world
Exited with error code : 0
我不清楚为什么你的命令没有产生错误。如果我给出一个错误的命令(例如,“echo”后面的尾随 space),我会得到一个例外:
Exception in thread "main" java.io.IOException: Cannot run program "/bin/echo ": error=2, No such file or directory
这可能是 OS 具体的。或者,也许您有一些其他 darknet
可执行文件被拾取。
您的命令必须将所有参数分成单独的部分 - 包括 thresholdFlag
。检查可执行文件是否存在是个好主意。如果没有,您应该检查它的位置或修复您的 Path 变量以确保可以找到它:
File darkpath = new File(darknetNamePath);
String [] cmd = new String[] { darkpath.getAbsolutePath(), "detect", configurationFlag, weightsFlag, imageFlag, "-thresh", String.valueOf(thresholds.getValue()) };
System.out.println("Path: "+darkpath+ " exists="+darkpath.exists());
System.out.println("exec "+Arrays.toString(cmd));
processBuilder.command(cmd);
也值得处理 STDERR,最简单的方法是在调用之前重定向 STDERR=>STDOUT processBuilder.start()
processBuilder.redirectErrorStream(true);
如果您希望 Java 在不添加绝对路径前缀的情况下启动可执行文件,它需要位于以下目录之一:
System.out.println("PATH COMPONENTS FOR JAVA LAUNCH:");
Arrays.asList(System.getenv("PATH").split(File.pathSeparator)).forEach(System.out::println);