簡體   English   中英

使用ProcessBuilder時Java不啟動GZIP命令

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

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