5 Stimmen

Speicherinterne Dekomprimierung mit zlib

Kann ich eine zlib-komprimierte Datei im Speicher lesen, ohne sie tatsächlich auf die Festplatte zu extrahieren? Es wäre schön, wenn Sie ein Snippet zur Verfügung stellen könnten.

0 Stimmen

10 Stimmen

Haben sie schon selbst etwas ausprobiert? nur ein tipp: "bitte stellen sie den code zur verfügung" ist eine schlechte art und weise, um hilfe zu bitten. niemand will kostenlos ihre arbeit für sie machen, aber die leute wollen ihnen helfen, ein problem zu lösen, das sie selbst nicht lösen können. formulieren sie ihre frage so, um bessere ergebnisse zu erzielen.

5 Stimmen

Du bekommst mehr Hilfe, wenn du es versuchst und uns dann zeigst, wo du stecken bleibst. Wenn Sie nicht wissen, wo Sie anfangen sollen, können Sie dies in Ihrer Frage angeben und einige Ideen nennen, die Sie in Betracht ziehen.

24voto

Raj Advani Punkte 3998

Hier ist eine zLib-Inflate-Routine, die einen Puffer im Speicher nimmt und in den bereitgestellten Ausgabepuffer dekomprimiert. Dies ist eine "One-Shot"-Funktion, da sie versucht, den gesamten Eingabepuffer auf einmal aufzublasen, und davon ausgeht, dass Sie ihr genug Platz gegeben haben, um alles unterzubringen. Es ist auch möglich, eine Multi-Shot-Funktion zu schreiben, die den Zielpuffer dynamisch nach Bedarf vergrößert.

int inflate(const void *src, int srcLen, void *dst, int dstLen) {
    z_stream strm  = {0};
    strm.total_in  = strm.avail_in  = srcLen;
    strm.total_out = strm.avail_out = dstLen;
    strm.next_in   = (Bytef *) src;
    strm.next_out  = (Bytef *) dst;

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

    int err = -1;
    int ret = -1;

    err = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
    if (err == Z_OK) {
        err = inflate(&strm, Z_FINISH);
        if (err == Z_STREAM_END) {
            ret = strm.total_out;
        }
        else {
             inflateEnd(&strm);
             return err;
        }
    }
    else {
        inflateEnd(&strm);
        return err;
    }

    inflateEnd(&strm);
    return ret;
}

Erläuterung:

src Quellpuffer, der die komprimierten Daten (gzip oder zlib) enthält
srcLen die Länge des Quellpuffers
dst Zielpuffer: der Zielpuffer, in den die Ausgabe geschrieben wird
dstLen die Länge des Zielpuffers

Rückgabewerte:

Z_BUF_ERROR: wenn dstLen nicht groß genug ist, um die aufgeblähten Daten aufzunehmen
Z_MEM_ERROR: wenn nicht genügend Speicherplatz für die Dekomprimierung vorhanden ist
Z_DATA_ERROR: wenn die Eingabedaten fehlerhaft waren

Andernfalls ist der Rückgabewert die Anzahl der nach dst geschriebenen Bytes.

2voto

Alex Punkte 965

Die von Raj Advani angebotene Lösung funktioniert nicht für Multistream-Zlib-Puffer. Lösung für gzip-Daten:

void decompress(Bytef *src, int src_len, Bytef *dst, int dst_len)
{
    z_stream strm  = {0};
    strm.zalloc = Z_NULL;
    strm.zfree  = Z_NULL;
    strm.opaque = Z_NULL;

    while (src_len > 0)
    {
        strm.total_in  = strm.avail_in  = src_len;
        strm.total_out = strm.avail_out = dst_len;
    strm.next_in   = src;
        strm.next_out  = (Bytef *) dst;
        assert(inflateInit2(&strm, (MAX_WBITS + 16)) == Z_OK);
        decompress_block(&strm, dst);
    unsigned int processed = src_len - strm.avail_in;
        src_len -= processed;
        src += processed;
    }
}

int decompress_block(z_stream *strm, void *dst)
{
    int ret;
    do
    {
        ret = inflate(strm, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR && ret != Z_NEED_DICT && ret != Z_MEM_ERROR && ret != Z_DATA_ERROR);
        assert(strm->avail_out > 0);
    }
    while (ret != Z_STREAM_END);
    inflateEnd(strm);
    assert(write(1, dst, strm->total_out) == strm->total_out);
    return 0;
}

https://github.com/uvoteam/gunzip_mmap

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X