zlib inflate Dekompression operation

Ich habe einen Daten-Puffer, enthält mehrere komprimierte Mitglieder, es könnte sein, deflate oder zlib-komprimiert Mitglied.

Fand ich, dass zlib inflate rufen Sie zurück Z_STREAM_END nach der Verarbeitung der ersten komprimierten block, Hier mehrere komprimierte Mitglied kann in jeder beliebigen Zahl(hier in meinem Beispiel die 3). Aber diese Daten kommen von anderen Seiten, die nicht kommuniziert detail über die Anzahl der komprimierten Mitglied in einem data.

So, wie könnte ich implementieren, die Verwendung von zlib inflate-Funktionalität, so dass es funktionieren könnte, die sich über mehrere komprimierte Mitglied ?

Folgenden ist ein Beispiel quick & dirty-Beispiel, in dem ich versuche zu erarbeiten, mein problem.
Dieses verwies die Sache mit zlib-1.2.5-Bibliothek.

/* example.c -- understanding zlib inflate/decompression operation
 */

#define CHECK_ERR(err, msg) { \
    if (err != Z_OK) { \
        std::cerr << msg << " error: " << err << std::endl; \
        exit(1); \
    } \
}

/* ===========================================================================
 * deflate() to create compressed data
 */
void test_deflate(std::vector<uint8_t> & input_data, std::vector<uint8_t>& compr)
{
    z_stream c_stream; /* compression stream */
    int err;

    compr.clear();

    c_stream.zalloc = (alloc_func)0;
    c_stream.zfree = (free_func)0;
    c_stream.opaque = (voidpf)0;

    err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
    CHECK_ERR(err, "deflateInit");

    c_stream.next_in  = &input_data[0];
    c_stream.avail_in = input_data.size();

    for (;;) {
        uint8_t c_buffer[10] = {};
        c_stream.next_out  = &c_buffer[0];
        c_stream.avail_out = 10;

        err = deflate(&c_stream, Z_FINISH);
        if (err == Z_STREAM_END)
        {
            for (int i = 0; i < (10 - c_stream.avail_out); i++)
                compr.push_back(c_buffer[i]);
            break;
        }
        CHECK_ERR(err, "deflate");
        for (int i = 0; i < (10 - c_stream.avail_out); i++)
            compr.push_back(c_buffer[i]);
    }

    std::cout << "Compressed data (size = " << std::dec << compr.size() << ") = ";
    for (int i = 0; i < compr.size(); i++)
        std::cout << (uint32_t) compr[i];
    std::cout << std::endl;

    err = deflateEnd(&c_stream);
    CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
 * Test inflate()
 */
void test_inflate(std::vector<uint8_t> &compr,
                  std::vector<uint8_t> &uncompr)
{
    int err;
    z_stream d_stream; /* decompression stream */

    uncompr.clear();

    d_stream.zalloc = Z_NULL;
    d_stream.zfree = Z_NULL;
    d_stream.opaque = Z_NULL;
    d_stream.avail_in = 0;
    d_stream.next_in = Z_NULL;
    err = inflateInit(&d_stream);
    CHECK_ERR(err, "inflateInit");

    d_stream.avail_in = compr.size();
    d_stream.next_in  = &compr[0];

    for(;;) {
        uint8_t d_buffer[10] = {};
        d_stream.next_out = &d_buffer[0];
        d_stream.avail_out = 10;

        err = inflate(&d_stream, Z_NO_FLUSH);

        if (err == Z_STREAM_END) {
            for (int i = 0; i < (10 - d_stream.avail_out); i++)
                uncompr.push_back(d_buffer[i]);
            if (d_stream.avail_in == 0)
                break;
        }

        CHECK_ERR(err, "inflate");
        for (int i = 0; i < (10 - d_stream.avail_out); i++)
            uncompr.push_back(d_buffer[i]);
    }
    err = inflateEnd(&d_stream);
    CHECK_ERR(err, "inflateEnd");

    std::cout << "Uncompressed data (size = " << std::dec << uncompr.size() << ") = ";
    for (int i = 0; i < uncompr.size(); i++)
        std::cout << (uint32_t) uncompr[i];
    std::cout << std::endl;
}


/* ===========================================================================
 * Usage:  example
 */

int main(int argc, char **argv)
{
    std::vector<uint8_t> input_data;
    std::vector<uint8_t> compr, multiple_compr;
    std::vector<uint8_t> uncompr;

    std::cout << "Input Data (in hex) = ";
    for (int i=0; i<32; i++) {
        input_data.push_back((uint8_t)i);
        if( i && (i % 2 == 0))
            std::cout << " ";
        std::cout << std::hex << (uint32_t)input_data[i];
    }
    std::cout << std::endl;

    //create compressed buffer-1 from input data
    test_deflate(input_data, compr);

    //copy compressed buffer-1 data into multiple compressed member buffer
    multiple_compr = compr;
    compr.clear();

    //create compressed buffer-2 from input data
    test_deflate(input_data, compr);

    //append data of compressed buffer-2 into multiple compressed member buffer
    for(int i=0; i< compr.size(); i++)
    {
        multiple_compr.push_back(compr[i]);
    }

    //create decompressed output
    test_inflate(multiple_compr, uncompr);

    //compare decompressed data with input data
    std::vector<uint8_t> final_data;
    final_data.push_back(input_data);
    final_data.push_back(input_data);
    if (final_data == uncompr)
       std::cout << "Matched" << std::endl;
    else
       std::cout << "Not Matched" << std::endl;

    return 0;
}

1) Hier ein zweites mal aufblasen Aufruf gibt Fehler, Aber ich will es erfolgreich fortgesetzt, warum Sie so arbeiten ?

2) Wenn ich Z_FINISH in der aufblasen Aufruf-argument kehrt er zurück mit Fehler, warum kann ich nicht mit Z_FINISH hier ?

Freundlicherweise korrigieren mein Beispiel und schlagen vor, einige optimierte Vorgehensweise, das gleiche zu tun.

  • Ein bisschen unklar. Erhalten Sie die chunks Daten und Dekomprimieren Sie es. Aber Sie weiß nicht, wie viele Stücke Sie bekommen kann? Es scheint, dies ist unabhängig von der gesamten zlib Geschichte, die Sie um ihn herum gewickelt.
  • Ja, es könnte sein, da ich in zlib inflate nennen, Noch, was ich wissen möchte ist, ob es einen Mechanismus, wie ich das zuweisen der Daten-Puffer zum avail_in, Wenn mehrere komprimierte Mitglied(d.h. 3) gibt es dann nach dem entpacken zunächst Mitglied avail_in haben noch sollte Daten von anderen komprimierten Mitglieder(d.h. 2) Kann ich nicht vorgegangen ? Noch, wie ich Lerne zlib Verwendungs-Idee ist nicht viel, klar, um mich noch richtig, Dass ist der Grund, warum es besser wäre, wenn Sie teilen könnten einige richtige Beispiel zur Verwendung von zlib inflate Nachdem er die zlib-Handbuch es ist noch nicht viel ist mir klar.
  • Ah, warten Sie. Also, nach dem entpacken, es könnte sein verbleibenden Daten in der Eingabe-Puffer. Siehe zlib.net/zlib_how.html, es wird von diesem über auf halbem Weg durch. (Nicht immer verwendet diese selbst, so werde ich zu bail-out hier.)
Schreibe einen Kommentar