2010-11-13 90 views
2

我在Windows機器中使用gzip實用程序。我壓縮一個文件並將其作爲blob存儲在數據庫中。當我想使用gzip實用程序解壓縮此文件時,我正在將此字節流寫入process.getOutputStream。但是在30KB之後,它無法讀取文件。它掛在那裏。將大文件作爲流發送到process.getOutputStream

嘗試使用內存參數,讀取和刷新邏輯。但是,如果我嘗試寫入文件,它的速度相當快。

OutputStream stdin = proc.getOutputStream(); 
Blob blob = Hibernate.createBlob(inputFileReader); 
InputStream source = blob.getBinaryStream(); 
byte[] buffer = new byte[256]; 
long readBufferCount = 0; 
while (source.read(buffer) > 0) 
{ 
    stdin.write(buffer); 
    stdin.flush(); 
    log.info("Reading the file - Read bytes: " + readBufferCount); 
    readBufferCount = readBufferCount + 256; 
} 
stdin.flush(); 

Regards, Mani Kumar Adari。

回答

1

我懷疑問題是,外部進程(連接到proc)或者是

  • 不讀它的標準輸入,或
  • 它寫的東西,你的Java應用程序是它的標準輸出不讀書。

請記住,Java使用一對「管道」與外部進程通信,並且這些緩衝區數量有限。如果超過管道的緩衝能力,寫入器進程將被阻塞寫入管道,直到讀取器進程從管道讀取足夠的數據以創建空間。如果讀者沒有閱讀,則管道鎖定。

如果您提供了更多的上下文(例如啓動gzip過程的應用程序的一部分),我可以更加明確。

隨訪

gzip.exe是Windows中的Unix工具,我們使用。 gzip.exe在命令提示符下工作正常。但不是與java程序。有什麼辦法可以增加java寫入管道的緩衝區大小。目前我很關注輸入部分。

在UNIX上,gzip工具,通常使用以下兩種方式之一:

  • gzip file壓縮file把它變成file.gz
  • ... | gzip | ...(或類似的東西)將其標準輸入的壓縮版本寫入其標準輸出。

我懷疑你是做了相當於後者,與Java應用程序作爲gzip命令的輸入源和輸出的目的地。這正是可以鎖定的場景......如果java應用程序沒有正確實現。例如:

Process proc = Runtime.exec(...); // gzip.exe pathname. 
    OutputStream out = proc.getOutputStream(); 
    while (...) { 
     out.write(...); 
    } 
    out.flush(); 
    InputStream in = proc.getInputStream(); 
    while (...) { 
     in.read(...); 
    } 

如果上面的應用程序的寫入階段寫入了太多的數據,它保證鎖定。

java應用程序和gzip之間的通信通過兩個管道進行。正如我上面所說的,管道會緩衝一定數量的數據,但這個數量相對較小,當然也是有限的。這是鎖定的原因。這裏是發生了什麼:

  1. gzip過程是創建一對管道連接到Java應用程序進程。
  2. Java應用程序將數據寫入其out
  3. gzip進程讀取從它的標準輸入的數據,將其壓縮並寫入到它的標準輸出。
  4. 步驟2和步驟3重複幾次,直至最後gzip進程試圖寫入其標準輸出塊。

發生了什麼事gzip已經寫入到它的輸出管道中,但是沒有任何東西可以讀取它。最終,我們達到了耗盡輸出管道緩衝區容量以及寫入管道塊的程度。

與此同時,Java應用程序仍在寫入out Stream,並且經過幾輪後,這也因爲填充另一個管道而阻塞。

唯一的解決方案是Java應用程序在同一時間讀取和寫入。簡單的做法是創建第二個線程,並從一個線程寫入外部進程,並從另一個線程讀取進程。 (更改Java緩衝或Java讀/寫大小將無濟於事,緩衝很重要的是在管道的OS實現中,並且無法從純Java改變它,如果有的話)。

+0

謝謝斯蒂芬。 gzip.exe是我們使用的Windows中的一個unix實用程序。 gzip.exe在命令提示符下工作正常。但不是與java程序。有什麼辦法可以增加java寫入管道的緩衝區大小。目前我很關注輸入部分。 – 2010-11-13 10:37:01

+0

@Mani Kumar Adari增加緩衝區,即使這是可行的,也無濟於事。您應該有讀取gzip.exe輸出的內容。或者,只需使用標準的GZIPInputStream類,就完全不需要gzip.exe。 – nos 2010-11-13 14:06:47