簡體   English   中英

7zip使用Java中的ProcessBuilder提取cmd

[英]7zip cmd extracting using ProcessBuilder in java

我在通過命令行使用Java 10 ProcessBuilder和7z.exe(18.05)將檔案提取到所需類別時遇到問題。 當我使用Windows CMD時,完全相同的命令可以正常工作,但是當我的JavaFX應用程序使用ProcessBuilder發出該命令時,該命令不再起作用:

    public static void decompress7ZipEmbedded(File source, File destination) throws IOException, InterruptedException {
    ProcessBuilder pb = new ProcessBuilder(
            getSevenZipExecutablePath(),
            EXTRACT_WITH_FULL_PATHS_COMMAND,
            quotifyPath(source.getAbsolutePath()),
            OUTPUT_DIRECTORY_SWITCH + quotifyPath(destination.getAbsolutePath())
    );
    processWithSevenZipEmbedded(pb);
}

   private static void processWithSevenZipEmbedded(ProcessBuilder pb) throws IOException, InterruptedException {
    LOG.info("7-zip command issued: " + String.join(" ", pb.command()));
    Process p = pb.start();
    new Thread(new InputConsumer(p.getInputStream())).start();
    System.out.println("Exited with: " + p.waitFor());
}

   public static class InputConsumer implements Runnable {
        private InputStream is;

        InputConsumer(InputStream is) {
            this.is = is;
        }

        @Override
        public void run() {
            try {
                int value = -1;
                while ((value = is.read()) != -1) {
                    System.out.print((char) value);
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }
            LOG.debug("Output stream completed");
        }
    }

public static String getSevenZipExecutablePath() {
    return FileUtil.quotifyPath(getDirectory() + "7z" + "/" + "7z");
}

public static String quotifyPath(String path) {
    return '"' + path + '"';
}

public class Commands {

    public static final String EXTRACT_COMMAND = "e";
    public static final String EXTRACT_WITH_FULL_PATHS_COMMAND = "x";
    public static final String PACK_COMMAND = "a";
    public static final String DELETE_COMMAND = "d";
    public static final String BENCHMARK_COMMAND = "b";
    public static final String LIST_COMMAND = "l";

}

public class Switches {

    public static final String OUTPUT_DIRECTORY_SWITCH = "-o";
    public static final String RECURSIVE_SWITCH = "-r";
    public static final String ASSUME_YES = "y";
}

該命令如下所示:

"C:/Users/blood/java_projects/AppRack/target/classes/7z/7z" x "D:\Pulpit\AppRack Sandbox\test\something\Something 2\Something2.7z" -o"D:\Pulpit\AppRack Sandbox\Something2"

以及ProcessBuilder的輸出:

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive for archives:
1 file, 59177077 bytes (57 MiB)

Extracting archive: D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
--
Path = D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
Type = 7z
Physical Size = 5917Exited with: 0
7077
Headers Size = 373
Method = LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 2


No files to process
Everything is Ok

Files: 0
Size:       0
Compressed: 59177077

它什么也沒做。 沒有創建所需的文件夾,什么也沒有。 使用CMD就像一個超級按鈕一樣工作(此處使用相同命令從Windows 10 CMD記錄日志):

7-Zip 18.05 (x64) : Copyright (c) 1999-2018 Igor Pavlov : 2018-04-30

Scanning the drive for archives:
1 file, 59177077 bytes (57 MiB)

Extracting archive: D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
--
Path = D:\Pulpit\AppRack Sandbox\test\Something\Something 2\Something2.7z
Type = 7z
Physical Size = 59177077
Headers Size = 373
Method = LZMA2:26 LZMA:20 BCJ2
Solid = +
Blocks = 2

Everything is Ok

Folders: 1
Files: 5
Size:       64838062
Compressed: 59177077

您是否知道是什么導致了此處的差異?為什么不執行任何操作就說“沒有要處理的文件,一切正常”? 我已經嘗試過先使用File類創建一個文件夾,但是這似乎不是問題,因為無論目標文件夾是否存在,提取之前結果都相同。

我已經嘗試了所有想到的方法,此刻我的想法已經用盡。 請與我分享您對此問題的任何建議。 非常感謝。

非常感謝您的幫助。

不要引用您的論點。 引號是為了命令shell的利益。 ProcessBuilder不是命令外殼;它不是命令外殼。 它直接執行命令,因此任何引號都被視為參數本身(即文件名)的一部分。 另外,pb.inheritIO(); 與手動使用流程流相比,這是查看子流程輸出的更好方法。

謝謝@VGR,這似乎是問題所在-在我刪除了上述命令中引用路徑的方法后,它就像一個超級按鈕,可以毫無問題地提取存檔! 因此結論是,在使用Java ProcessBuilder時,我不應該在路徑中使用引號。

我也使用過pb.inheritIO(),您是對的,用這種方法來管理它會更好,更容易。

public static void decompress7ZipEmbedded(File source, File destination) throws IOException {
    ProcessBuilder pb = new ProcessBuilder().inheritIO().command(
            getSevenZipExecutablePath(),
            EXTRACT_WITH_FULL_PATHS_COMMAND,
            source.getAbsolutePath(),
            OUTPUT_DIRECTORY_SWITCH + destination.getAbsolutePath(),
            OVERWRITE_WITHOUT_PROMPT
    );
    processWithSevenZipEmbedded(pb);
}

private static void processWithSevenZipEmbedded(ProcessBuilder pb) throws IOException {
    LOG.info("7-zip command issued: " + String.join(" ", pb.command()));
    pb.start();
}

public class Commands {
    public static final String EXTRACT_WITH_FULL_PATHS_COMMAND = "x"; 
}

public class Switches {
    public static final String OUTPUT_DIRECTORY_SWITCH = "-o";
    public static final String OVERWRITE_WITHOUT_PROMPT = "-aoa";
}

雙擊文件7zip.chm或啟動7-Zip,然后打開“幫助”並閱讀幫助頁面的命令行版本-第一行7z [...] [...]的語法。 清楚地解釋了,首先必須指定命令x,其次應該是-o之類的開關,最好是-才是最后一個開關,然后是歸檔文件名以及要提取的文件/文件夾名稱之類的最后進一步參數。 也可以在歸檔文件名之后指定開關,但是不建議這樣做,盡管-o幫助頁面上的示例也以-o結尾。

謝謝@Mofi的提示。 我使用-aoa開關而不是-y,它終於開始按我的意願工作-覆蓋文件而沒有任何提示。 我按預期的方式保留了其余命令,因此最終看起來像這樣:

C:/Users/blood/java_projects/AppRack/target/classes/7z/7z" x D:\Pulpit\AppRack Sandbox\test\Test\Test 2\Test.7z -oD:\Desktop\AppRack Sandbox\Test 2 -aoa

再次非常感謝您的幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM