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.
Antworten
Zu viele Anzeigen?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.
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;
}
0 Stimmen
zlib.net/zlib_how.html
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.
7 Stimmen
Es wäre schön, wenn ich für die Arbeit bezahlt würde und nicht Sie ;)