Zlib 缩小输入大于原始输入字符串?
Zlib deflated input is larger than original input string of chars?
我对 zlib 压缩 char
类型字符串的输入感到有点困惑。下面我有发布的代码输出,我注意到 input 字符串与输出相比 shorter 以字节为单位。
未压缩的大小为 8 字节,压缩后的大小为 12?我是不是看错了?
这是代码。
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <iostream>
#include "zlib.h"
void print( char *array, int length)
{
for(int index = 0; index < length; index++)
std::cout<<array[index];
std::cout<<std::endl;
}
void clear( char *array, int length)
{
for(int index = 0; index < length; index++)
array[index] = 0;
}
int main()
{
const int length = 30;
char a[length] = "HHHHHHH";
char b[length] = "";
char c[length] = "";
print( a, length);
std::cout<<std::endl;
uLong ucompSize = strlen(a)+1; // "string" + NULL delimiter.
std::cout<<"ucompSize: "<<ucompSize<<std::endl;
uLong compSize = compressBound(ucompSize);
std::cout<<"compSize: "<<compSize<<std::endl;
std::cout<<std::endl;
// Deflate
compress((Bytef *)b, &compSize, (Bytef *)a, ucompSize);
std::cout<<"ucompSize: "<<ucompSize<<std::endl;
std::cout<<"compSize: "<<compSize<<std::endl;
print( b, length);
std::cout<<std::endl;
// Inflate
uncompress((Bytef *)c, &ucompSize, (Bytef *)b, compSize);
std::cout<<"ucompSize: "<<ucompSize<<std::endl;
std::cout<<"compSize: "<<compSize<<std::endl;
print( c, length);
return 0;
}
这是输出。
HHHHHHH
ucompSize: 8
compSize: 21
ucompSize: 8
compSize: 12
x�� ��
ucompSize: 8
compSize: 12
HHHHHHH
Process returned 0 (0x0) execution time : 0.013 s
Press ENTER to continue.
这些字节中至少有六个是压缩流前面的两个魔术字节 (header),将其标识为 zlib-compressed 文件,还有四个字节用于校验和。不计算格式的开销最多会留下六个字节的压缩数据,这比您的输入流要小。
有关文件格式的更多详细信息,请参阅 RFC 的 §2.2。您可以使用 xxd
或 hexdump
等工具来调查十六进制字节组,以确认输出流的哪些部分是开销的,哪些是压缩数据。
如果您想避免这种情况,您可以使用 compressBound()
函数来检查大小是否实际上大于您当前的数据:
ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
compressBound()
returns an upper bound on the compressed size after
compress()
or compress2()
on sourceLen
bytes. It would be used before
a compress()
or compress2()
call to allocate the destination buffer.
compress()
函数使用 zlib 格式,在原始压缩数据周围放置 two-byte header 和 four-byte 尾部。即使原始压缩数据小于原始字符串,您也会从包装器中多获得六个字节。对于空字符串,根本没有字节,原始压缩数据是两个字节。所以 zlib 流的最小大小是八个字节。八个重复的输入字节可以产生短至四个字节的原始压缩数据,因此最小 zlib-wrapped 结果是十个字节。
一般来说,您需要更大的输入才能使无损压缩有效。
我对 zlib 压缩 char
类型字符串的输入感到有点困惑。下面我有发布的代码输出,我注意到 input 字符串与输出相比 shorter 以字节为单位。
未压缩的大小为 8 字节,压缩后的大小为 12?我是不是看错了?
这是代码。
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <iostream>
#include "zlib.h"
void print( char *array, int length)
{
for(int index = 0; index < length; index++)
std::cout<<array[index];
std::cout<<std::endl;
}
void clear( char *array, int length)
{
for(int index = 0; index < length; index++)
array[index] = 0;
}
int main()
{
const int length = 30;
char a[length] = "HHHHHHH";
char b[length] = "";
char c[length] = "";
print( a, length);
std::cout<<std::endl;
uLong ucompSize = strlen(a)+1; // "string" + NULL delimiter.
std::cout<<"ucompSize: "<<ucompSize<<std::endl;
uLong compSize = compressBound(ucompSize);
std::cout<<"compSize: "<<compSize<<std::endl;
std::cout<<std::endl;
// Deflate
compress((Bytef *)b, &compSize, (Bytef *)a, ucompSize);
std::cout<<"ucompSize: "<<ucompSize<<std::endl;
std::cout<<"compSize: "<<compSize<<std::endl;
print( b, length);
std::cout<<std::endl;
// Inflate
uncompress((Bytef *)c, &ucompSize, (Bytef *)b, compSize);
std::cout<<"ucompSize: "<<ucompSize<<std::endl;
std::cout<<"compSize: "<<compSize<<std::endl;
print( c, length);
return 0;
}
这是输出。
HHHHHHH
ucompSize: 8
compSize: 21
ucompSize: 8
compSize: 12
x�� ��
ucompSize: 8
compSize: 12
HHHHHHH
Process returned 0 (0x0) execution time : 0.013 s
Press ENTER to continue.
这些字节中至少有六个是压缩流前面的两个魔术字节 (header),将其标识为 zlib-compressed 文件,还有四个字节用于校验和。不计算格式的开销最多会留下六个字节的压缩数据,这比您的输入流要小。
有关文件格式的更多详细信息,请参阅 RFC 的 §2.2。您可以使用 xxd
或 hexdump
等工具来调查十六进制字节组,以确认输出流的哪些部分是开销的,哪些是压缩数据。
如果您想避免这种情况,您可以使用 compressBound()
函数来检查大小是否实际上大于您当前的数据:
ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
compressBound()
returns an upper bound on the compressed size aftercompress()
orcompress2()
onsourceLen
bytes. It would be used before acompress()
orcompress2()
call to allocate the destination buffer.
compress()
函数使用 zlib 格式,在原始压缩数据周围放置 two-byte header 和 four-byte 尾部。即使原始压缩数据小于原始字符串,您也会从包装器中多获得六个字节。对于空字符串,根本没有字节,原始压缩数据是两个字节。所以 zlib 流的最小大小是八个字节。八个重复的输入字节可以产生短至四个字节的原始压缩数据,因此最小 zlib-wrapped 结果是十个字节。
一般来说,您需要更大的输入才能使无损压缩有效。