概述
我正在使用libbzip2
库中的低级调用:BZ2_bzCompressInit()
,BZ2_bzCompress()
和BZ2_bzCompressEnd()
将数据块压缩为标准输出。
我正在从更高级别的调用迁移工作代码,因为我有一个字节流进来,我想压缩离散块的 sets 中的那些字节(离散块< / em>是一组字节,包含一组感兴趣的标记 - 我的输入在逻辑上被分成这些组的组。)
一组完整的块可能包含500个块,我想压缩到一个bzip2流并写入标准输出。
在一个集合中,使用下面概述的伪代码,如果我的示例缓冲区一次能够容纳101个块,我会打开一个新流,在101,101,101,101和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... */
问题
cumulativeBytesWritten
(或者,具体而言,bzBytesWritten
),我将如何解决这个问题? 我一直在调试版本中跟踪这些值,而我似乎并没有“重复计算”bzBytesWritten
值。在每次成功cumulativeBytesWritten
次传递后,此值将被计算并使用一次以增加BZ2_bzCompress()
。
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);
这可能是一个简单的解决方案,但是在调试可能出错的过程中,我已经在桌子上敲了几天,而且我没有取得多大进展。谢谢你的任何建议。
答案 0 :(得分:1)
在回答我自己的问题时,似乎我错误地计算了写入的字节数。我不应该使用total_out_*
成员。以下更正正常:
bzBytesWritten = sizeof(bzBuffer) - bzStream.avail_out;
其余的计算如下。