![](/img/trans.png)
[英]Java: “UNIXProcess” error when using “exec” or “ProcessBuilder” to run a command
[英]Java is not launching GZIP command when using ProcessBuilder
我肯定在嘗試此操作的盒子上安裝了GZIP
。 但是,當我在Java中運行此文件時,看不到正在創建的壓縮文件。 我正在處理的文件是非常大的文件,因此我不希望將其讀入內存。 以下是我為此編寫的代碼。 我的直覺是它與重定向有關。
try {
ProcessBuilder builder = new ProcessBuilder("gzip", "-9", "<", filename, ">", zippedFilename);
builder.start();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
首先,值得注意的是,您可以通過避免使用外部進程並使用Java進行壓縮來簡化此操作:
Path input = Paths.get(filename);
Path zipped = Paths.get(zippedFilename);
try (OutputStream out = new GZIPOutputStream(
new BufferedOutputStream(
Files.newOutputStream(zipped)))) {
Files.copy(input, out);
}
這具有完全多平台的額外優勢。 在Windows上不需要/ usr / bin / gzip,也不需要Unix工具。 它不會實現-9
選項,但我將檢查該選項實際獲得了多少額外的壓縮,並權衡是否值得擁有一個便攜式性較低的程序。
對於其他命令(或-9
非常重要),ProcessBuilder命令無法使用<
和>
進行輸入和輸出的重定向,出於相同的原因,C程序將無法通過以下調用來完成重定向:
/* Does not work. */
execl("/usr/bin/gzip", "gzip", "-9", "<", filename, ">", zippedFilename, (char *)NULL);
在外殼程序(如bash)中運行命令時,外殼程序會截取<
和>
,從命令中剝離它們和它們的后續參數,並在不使用它們的情況下調用實際程序。 因此,鍵入以下內容:
gzip -9 < filename > filename.gz
實際上導致外殼運行gzip
僅帶有一個參數: -9
。 然后,shell從filename
讀取並將其傳遞給gzip程序進程的標准輸入描述符。 類似地,shell從相同的gzip程序調用中捕獲標准輸出,並將其寫入filename.gz
。
在此過程中,gzip進程不知道其輸入來自何處或其輸出在何處。 它只是從自己的標准輸入讀取並寫入其標准輸出。
直接調用程序時,將繞過外殼程序,因此對<
和>
沒有特殊處理。 這意味着您當前的ProcessBuilder命令與此Unix命令等效:
gzip -9 '<' filename '>' filename.gz
這意味着您要調用帶有一個選項和四個文件參數的gzip,這將導致gzip首先查找名稱為一個字符長的文件,一個字面名為<
的文件,然后將其壓縮版本寫入<.gz
。 然后,它將對名為filename
,然后對名為>
的文件,對文件名filename.gz
。
因此,如您所見,Unix命令對重定向一無所知。 <
和>
字符不能直接傳遞給它們。
但是,您可以使用ProcessBuilder模擬重定向:
ProcessBuilder builder = new ProcessBuilder("gzip", "-9");
builder.inheritIO();
builder.redirectInput(new File(filename));
builder.redirectOutput(new File(zippedFilename));
Process process = builder.start();
對InheritIO()的調用將導致外部進程的標准錯誤(即,任何錯誤消息)出現在Java程序的標准錯誤上。 否則,您將無法指示程序為何失敗。 (如果我們沒有重定向它們,它將對標准輸入和標准輸出執行相同的操作。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.