2012-10-25 80 views
3

概覽用bzip2的低級程序對數據進行壓縮

我使用的libbzip2庫中的底層調用的大塊:BZ2_bzCompressInit()BZ2_bzCompress()BZ2_bzCompressEnd()壓縮數據到標準輸出的塊。

我遷移更高級別的呼叫工作代碼,因爲我進來的字節流,我想在套壓縮這些字節離散塊(一離散塊是一組字節的那包含一組感興趣的令牌 - 我的輸入在邏輯上被劃分爲這些塊的組)。

一組完整的塊可能包含500個塊,我想壓縮到一個bzip2流並寫入標準輸出。

在一個集合中,使用下面概述的僞代碼,如果我的示例緩衝區一次可以容納101個塊,我會打開一個新流,壓縮500個塊,還有最後一批96個關閉流的組塊。

的問題

的問題是,我bz_stream結構實例,這使壓縮後的字節數的軌道在BZ2_bzCompress()常規的單道,似乎聲稱自己是寫比更加壓縮字節最終壓縮文件中的總字節數。

例如,壓縮輸出可能是一個真實大小爲1234字節的文件,而報告的壓縮字節數(我在調試時跟蹤)的數量比1234字節(比如2345字節)略高。

我粗糙的僞代碼分爲兩部分。

第一部分是我做什麼來壓縮塊的一個子集的草圖(我知道我有這樣的一個又一個子集來):

bz_stream bzStream; 
unsigned char bzBuffer[BZIP2_BUFFER_MAX_LENGTH] = {0}; 
unsigned long bzBytesWritten = 0UL; 
unsigned long long cumulativeBytesWritten = 0ULL; 
unsigned char myBuffer[UNCOMPRESSED_MAX_LENGTH] = {0}; 
size_t myBufferLength = 0; 

/* initialize bzStream */ 
bzStream.next_in = NULL; 
bzStream.avail_in = 0U; 
bzStream.avail_out = 0U; 
bzStream.bzalloc = NULL; 
bzStream.bzfree = NULL; 
bzStream.opaque = NULL; 
int bzError = BZ2_bzCompressInit(&bzStream, 9, 0, 0); 

/* bzError checking... */ 

do 
{ 
    /* read some bytes into myBuffer... */ 

    /* compress bytes in myBuffer */ 
    bzStream.next_in = myBuffer; 
    bzStream.avail_in = myBufferLength; 
    bzStream.next_out = bzBuffer; 
    bzStream.avail_out = BZIP2_BUFFER_MAX_LENGTH; 
    do 
    { 
     bzStream.next_out = bzBuffer; 
     bzStream.avail_out = BZIP2_BUFFER_MAX_LENGTH; 
     bzError = BZ2_bzCompress(&bzStream, BZ_RUN); 

     /* error checking... */ 

     bzBytesWritten = ((unsigned long) bzStream.total_out_hi32 << 32) + bzStream.total_out_lo32; 
     cumulativeBytesWritten += bzBytesWritten; 

     /* write compressed data in bzBuffer to standard output */ 
     fwrite(bzBuffer, 1, bzBytesWritten, stdout); 
     fflush(stdout); 
    } 
    while (bzError == BZ_OK); 
} 
while (/* while there is a non-final myBuffer full of discrete chunks left to compress... */); 

現在我們包的輸出:

/* read in the final batch of bytes into myBuffer (with a total byte size of `myBufferLength`... */ 

/* compress remaining myBufferLength bytes in myBuffer */ 
bzStream.next_in = myBuffer; 
bzStream.avail_in = myBufferLength; 
bzStream.next_out = bzBuffer; 
bzStream.avail_out = BZIP2_BUFFER_MAX_LENGTH; 
do 
{ 
    bzStream.next_out = bzBuffer; 
    bzStream.avail_out = BZIP2_BUFFER_MAX_LENGTH; 
    bzError = BZ2_bzCompress(&bzStream, (bzStream.avail_in) ? BZ_RUN : BZ_FINISH); 

    /* bzError error checking... */ 

    /* increment cumulativeBytesWritten by `bz_stream` struct `total_out_*` members */ 
    bzBytesWritten = ((unsigned long) bzStream.total_out_hi32 << 32) + bzStream.total_out_lo32; 
    cumulativeBytesWritten += bzBytesWritten; 

    /* write compressed data in bzBuffer to standard output */ 
    fwrite(bzBuffer, 1, bzBytesWritten, stdout); 
    fflush(stdout); 
} 
while (bzError != BZ_STREAM_END); 

/* close stream */ 
bzError = BZ2_bzCompressEnd(&bzStream); 

/* bzError checking... */ 

的問題

  • 我是calcula ()(或者,具體地說,bzBytesWritten)不正確,我該如何解決這個問題?

我一直在調試版本中跟蹤這些值,我似乎沒有「重複計算」bzBytesWritten值。在每個成功的BZ2_bzCompress()通過後,此值將被計數並用於一次增量cumulativeBytesWritten

  • 或者,我不理解正確使用bz_stream狀態標誌嗎?

例如,以下壓縮並保持bzip2流打開,只要我不斷髮送一些字節?

bzError = BZ2_bzCompress(&bzStream, BZ_RUN); 

同樣地,可以在下面的陳述壓縮數據,只要存在至少一些字節可用從bzStream.next_in指針(BZ_RUN)訪問,然後流被包裹起來時,有沒有更多的字節可用(BZ_FINISH)?

bzError = BZ2_bzCompress(&bzStream, (bzStream.avail_in) ? BZ_RUN : BZ_FINISH); 
  • 或者說,我不能使用這些低級別的調用正確呢?我應該回到使用更高級別的調用來連續追加一組壓縮的數據到一個主文件嗎?

這可能有一個簡單的解決方案,但是在調試可能出錯的過程中,我已經把我的頭撞到了桌子上幾天了,而且我沒有取得太大的進展。感謝您的任何建議。

回答

1

在回答我自己的問題時,看起來我錯誤地計算了寫入的字節數。我不應該使用total_out_*成員。下面的修正工作正常:

bzBytesWritten = sizeof(bzBuffer) - bzStream.avail_out; 

計算的其餘部分遵循。