2 Mart 2020 Pazartesi

ZLib Kütüphanesi

Deflate Algoritması
Kullanılan parametreler
Açıklaması şöyle
...the compression algorithm (Deflate) in GZip is not strictly bijective. To elaborate: For some data, there's more than one possible compressed output depending on the algorithmic implementation and used parameters. So there's no guarantee at all that Apple GZip and gzip 1.6 will return the same compressed output. These outputs are all valid GZip streams, the standard just guarantees that every of these possible outputs will be decompressed to the same original data.
ZLib Kütüphanesi
ZLib altta Deflate algoritmasını kullanır. ZLib bellekte sıkıştırmak için kullanılır. zlib eğer verinin içinde hep farklı byte'lar varsa veriyi daha da büyütür. Örneğin 0-255 arasında değer içeren bir byte dizisi, normal sıkıştırma ile 266 byte'a çıkar. Sadece 1 değerini içeren 255 byte uzunluğundaki bir dizi ise 12 byte olarak sıkıştırılır.

Zlib (RFC 1950) ve GZip (RFC 1952) farklı header'lar kullanmalarına rağmen aynı sıkıştırma algoritmasını kullanırlar.

ZLib Header
2 byte uzunluğundadır.
0   1
+---+---+
|CMF|FLG|
+---+---+
Compression Method and Flags ve Flags byte'larından oluşur. Hex 78 dışında bir değer taşıdığını görmedim.

zlib kütüphanesi
compress ve decompress isimli tek çağrıda sıkıştırma ve açma işlemlerini yapmamızı sağlayan iki metod var. Bu iki metod z_stream ile uğraşmaktan çok daha kolay.
char a[50] = "Hello, world!";
char b[50];
char c[50];

uLong ucompSize = strlen(a)+1; // "Hello, world!" + NULL delimiter.
uLong compSize = compressBound(ucompSize);

// Deflate
compress((Bytef *)b, &compSize, (Bytef *)a, ucompSize);

// Inflate
uncompress((Bytef *)c, &ucompSize, (Bytef *)b, compSize);
Şöyle bir açıklama var ama ne olduğunu anlamadım.
zlib provides the Z_HUFFMAN_ONLY compression strategy, which only uses Huffman coding to compress the input. The string matching zlib normally uses is turned off with that option.

boost sıkıştırma
Zlib sıkıştırma ve açma işlemi için zlib_compressor, zlib_decompressor sınıfları kullanılır.
Bu iki sınıf altta zlib kütüphanesini kullanırlar. zlib kütüphanesini ilklendirmek için deflate metodunu şöyle çağırırlar.
z_stream strm;

strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;


deflateInit2 (&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
              15, //windowBits
              8,  //mem Bits
              Z_DEFAULT_STRATEGY);
Sıkıştırmak için önce using ekleriz ki kod anlaşılır olsun.
namespace io = boost::iostreams;
Sonra bir filtering_ostream tanımlarız ve zincire zlib_compressor nesnesini ekleriz. zlib_compressor nesnesine zlib_params parametreleri geçilebiliyor. Şöyle yaparız.
zlib_params p(
            9, //zlib::default_compression yerine kullan
            zlib::deflated,
            zlib::default_window_bits,
            zlib::default_mem_level,
            zlib::default_strategy,
            true
    );
os.push(zlib_decompressor(p));
Ancak sıkıştırma seviyesi alanı hariç diğer parametrelerle oynamanın bence bir anlamı yok. Belki sadee noheader alanı 2 byte'lık header'dan kurtulmamızı sağlayabilir.
io::filtering_ostream os;
os.push(io::zlib_compressor());
Sıkıştırılmış verinin yazılacağı veriyapısını zincire ekleriz.
std::vector<uint8_t> result;
os.push(std::back_inserter(result));
Eğer istersek filtering_ostream yerine, filtering_streanbuf ta kullanabiliriz. Şöyle yaparız.
bio::filtering_streambuf<bio::output> os;
os.push(bio::zlib_compressor());
Veriyi yazarız.
std::vector<byte_t> data=...;
io::write(os, reinterpret_cast<const char*>(&data[0]), data.size());
Veriyi şöyle de kopyalayabiliriz.
std::stringstream ss;
ss << "...";
io::copy(ss, out);
Sıkıştırılmış veri result nesnesindedir.

boost açma
Örnek ver.

Java
Deflater Sınıfı ve Inflater Sınıfı yazılarına taşıdım.

.Net
.Net ile ZLib için bir stream sınıfı gelmiyor. Ancak Deflate sınıfları var. Tek yapmamız gereken ZLib'in kullandığı 2 byte uzunluğundaki header alanını atlamak. Açma için şöyle yaparız.
using (var stream = new MemoryStream(bytes,2, bytes.Length - 2))
using (var inflater = new DeflateStream(stream, CompressionMode.Decompress))
using (var streamReader = new StreamReader(inflater))
{
    return streamReader.ReadToEnd();
}

Hiç yorum yok:

Yorum Gönder