【Linux】linux下zlib圧縮とcrc 32検査


最近のプロジェクトでは、転送データ量を減らすために、データの圧縮と解凍が必要です.ネット上で検索して前のプロジェクトの中でzlibの1つの比較的に小さいライブラリを使ったことを見て、具体的な住所は公式サイトを見てください.データの解凍だけなら、公式サイトのチュートリアルに直接フォローすればいいです.このアドレスは圧縮と解凍の実現を簡単に与えた.しかし、私たちのプロジェクトをしたいのは、crc 32の検証も参照しているため、解凍と圧縮の前にデータのcrc生成と検証が必要です.しばらくの間模索したあげく、ついに流れが通じた.
crc32
crc 32の紹介
crc 32検査
crcチェックには、一般的に2つの方法があります.
  • はcrc検証コードを単独で検証する.この方式では、元のデータとcrcチェックコードは別々に記憶され、別々にチェックされる.
  • 元データcrcチェックコードを一緒にチェックし、チェックするときにどの部分がデータで、どの部分がcrcチェックコードなのか分からない.この方法を採用すると使いやすくなりますが、次のコード例もこの方法を採用しています.

  • zlib
    圧縮アルゴリズムの紹介
    よく使われる圧縮アルゴリズムは基本的に2種類あり、これはzlibライブラリでも紹介されています.-huffman符号化は、主に長くなる文字を用いて圧縮符号化される.出現する確率が高いほど、その符号化が短くなり、最終的な符号化長が短くなる.-lz 777、これは自分で検索しましょう.主に次の文字の位置を距離標識で説明します.
    zlibとcrc 32の使用
    このテストコードは主に圧縮、解凍の2つの関数を含む.テストコードでは圧縮したデータに対してcrcチェックコードを生成し,チェックコードを圧縮データの末尾に追加し,最終的な圧縮データとする.解凍関数は、最終的な圧縮データ(元の圧縮データとcrcチェックコード)を解凍操作する.
    解凍関数
    int DeCompress(const unsigned char * src, long src_len, unsigned char * dest, long * dest_len)
    {
        z_stream stream;
        int err;
        if (crc32(0, src, src_len) != 0xFFFFFFFF)
        {   
            printf("crc error: %d
    "
    , Z_BUF_ERROR); return Z_BUF_ERROR; } stream.next_in = (Bytef*)src; stream.avail_in = (uInt)src_len; /* Check for src > 64K on 16-bit machine: */ if ((uLong)stream.avail_in != src_len) return Z_BUF_ERROR; stream.next_out = dest; stream.avail_out = (uInt)*dest_len; if ((uLong)stream.avail_out != *dest_len) return Z_BUF_ERROR; stream.zalloc = (alloc_func)0; stream.zfree = (free_func)0; err = inflateInit2(&stream, -MAX_WBITS); //err = inflateInit(&stream); if (err != Z_OK) return err; err = inflate(&stream, Z_FINISH); if (err != Z_STREAM_END) { inflateEnd(&stream); if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0)) return Z_DATA_ERROR; return err; } *dest_len = stream.total_out; err = inflateEnd(&stream); return err; }

    あっしゅくかんすう
    int Compress(const unsigned char * src, long src_len, unsigned char * dest, long * dest_len)
    {
        z_stream stream;
        int err = 0;
    
        stream.zalloc = (alloc_func)0;
        stream.zfree = (free_func)0;
        // setup "a" as the input and "b" as the compressed output
        stream.avail_in = (uInt)src_len; // size of input, string + terminator
        stream.next_in = (Bytef *) src; // input char array
        stream.avail_out = (uInt) *dest_len; // size of output
        stream.next_out = (Bytef *)dest; // output char array
    
    
        deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY );
        deflate(&stream, Z_FINISH); // the actual compression work.
        deflateEnd(&stream);
    
        // This is one way of getting the size of the output
        *dest_len = stream.total_out;
        return err;
    }

    テストコード
    int main()
    {
        unsigned char a[] = "123123123123123123123";
        unsigned char b[124];
    
        size_t size = sizeof(b);
        Compress(a, sizeof(a), b, (long int  *)(&size));
        printf("a: %s, compress size: %lu
    "
    , a, size); uLong crc = crc32(0L, Z_NULL, 0); printf("crc: %lu, char: %u
    "
    , crc, b[size + 1]); crc = ~crc32(crc, b, size); b[8] = (crc & 0xFF); b[9] = ((crc >> 8) & 0xFF); b[10] = ((crc >> 16) & 0xFF); b[11] = ((crc >> 24) & 0xFF); b[12] = 0; size = size + 4; unsigned char c[124]; long int s = 124; DeCompress(b, size, c, (long int *)(&s)); printf("a: %s, c: %s
    "
    , a, c); return 1; }

    ちょっと言って、この中で出会った問題:1、crc検査に失敗して、直接失敗に戻りました.この当時の脳障害は、解凍前のデータにcrcチェックコードを作り、データの末尾に追加した.しかし、解凍時に圧縮したデータをcrcチェックするので、問題があるに違いない.そして論理を整理して圧縮後のデータに対してcrcチェックコードを生成し,データの末尾に追加する.しかし、まだ問題があります.前のプロジェクトコードを見て、crcチェックコードを逆にしたことに気づきました.なぜか分かりません.その後、取反を加えてcrc検査に合格した.
    2、解凍する時、データはずっと正常に解凍できない.ここは最初は公式サイトで指定されたチュートリアルを参考にしたので、圧縮するときはdeflateInitメソッドを使って、長い間デバッグしてもデバッグできませんでした.その後、解凍時の方法はinflateInit 2で、圧縮時にdeflateInitとdeflateInit 2の方法の違いもあるのではないかと気づき、文書を調べてみるとやはりdeflateInit 2の方法があることがわかりました.deflateInit 2メソッドの使用、デバッグ、修正、プログラムの通過を確認し、圧縮前のメソッドを正しく出力します.ここで注意しなければならないのは、圧縮と解凍の2つの方法で呼び出され、それぞれinflateInitとdeflateInit、inflateInit 2とdeflateInit 2であり、各パラメータが伝達するパラメータが異なり、最終的な結果も異なる.いずれかの圧縮方法でデータを圧縮するには、他の同じ解凍方法でデータを解凍する必要があります.そうしないと、データが間違ってしまいます.