[英]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.