使用 ProcessBuilder 的问题

Issues Using ProcessBuilder

我在使用 ProcessBuilder.start(); 时遇到一些问题。

下面是代码的示例:

List<String> listOfStrings = new ArrayList<String>();
myListOfString.add("zip");
myListOfString.add("-r");
myListOfString.add(destinationPath);
myListOfString.add(newFilePath);

File zipFile = new File(workingDirectory, fileName + ".zip");

ProcessBuilder processBuilder = new ProcessBuilder(listOfStrings);
prcoessBuilder.directory(workingDirectory);
try{
  Process p = processBuilder.start();
  ...
  ...
  ...

workingDirectory 已使用 workingDirectory.isDirectory().

验证为工作目录

问题发生在 Process p = processBuilder.start();,它抛出 IOException

下面是堆栈跟踪:

java.io.IOException: Cannot run program "zip" (in directory "<Path to workingDirectory>"): error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    ...
    ...
    ...

workingDirectory 不指向特定文件(例如:/path/to/,而不是 /path/to/file.zip),但是,它是一个有效的目录。这可能是问题所在吗?

由于项目的性质,我无法给出确切的代码,但我无法想象如果它在 Process p = processBuilder.start(); 时崩溃,输入会不会有太大影响,然而,这就是我伸出援手的原因所以可能是这样。

如果需要任何说明,请告诉我。

错误信息说Java在当前目录或路径上没有找到名为zip的可执行文件,可以看到:

String systemPath = System.getenv("PATH");
System.out.println("PATH="+systemPath);

修复您的启动器以包含“zip”的完整路径或修复用于您的 Java VM 的路径以包含包含 zip.

的目录
myListOfString.add("/the/path/to/zip");

或类似的东西(取决于您的 shell / 终端)

export PATH=/the/path/to:$PATH

正如@Abra 所建议的,有更好的方法可以在 Java 内压缩而不依赖 ProcessBuilder,例如:

public static void zip(Path dir, Path zip) throws IOException
{
    Map<String, String> env = Map.of("create", "true");
    try (FileSystem fs = FileSystems.newFileSystem(zip, env))
    {
        // This predicate processed the action because it makes use of BasicFileAttributes
        // Rather than process a forEach stream which has to call Files.isDirectory(path)
        BiPredicate<Path, BasicFileAttributes> foreach = (p,a) -> {
            copy(p,a, fs.getPath("/"+dir.relativize(p)));
            return false;
        };

        Files.find(dir, Integer.MAX_VALUE, foreach).count();
    }
    System.out.println("ZIPPED "+dir +" to "+zip);
}
private static void copy(Path from, BasicFileAttributes a, Path target)
{
    System.out.println("Copy "+(a.isDirectory() ? "DIR " : "FILE")+" => "+target);
    try
    {
        if (a.isDirectory())
            Files.createDirectories(target);
        else if (a.isRegularFile())
            Files.copy(from, target, StandardCopyOption.REPLACE_EXISTING);
    }
    catch (IOException e)
    {
        throw new UncheckedIOException(e);
    }
}