zlib inflate: avail_out ist falsch



  • Hey,

    ich möchte den inflate() Algorithmus der zlib Library auf einen Buffer anwenden und das Ergebnis in einer Datei abspeichern.

    Ich habe dabei diesen Code wie folgt abgewandelt:

    #define CHUNK 16384
    
    byte chunkBuf[CHUNK];
    
    int inf(byte *src, size_t srcsize, FILE *dest)
    {
        int ret;
        unsigned have;
        unsigned char in[CHUNK];
    	unsigned long srcpos = 0;
    	z_stream strm;
    
        /* allocate inflate state */
        strm.zalloc = Z_NULL;
        strm.zfree = Z_NULL;
        strm.opaque = Z_NULL;
        strm.avail_in = 0;
        strm.next_in = Z_NULL;
        ret = inflateInit(&strm);
    	if (ret != Z_OK) {
    		printf("ERR: inf: %i\n",ret);
    		return ret;
    	}
        /* decompress until deflate stream ends or end of file */
        do {
    		if (srcsize - srcpos > CHUNK) {
    			memcpy(in,src+srcpos,CHUNK);
    			strm.avail_in = CHUNK;
    			srcpos += CHUNK;
    		} else if (srcsize - srcpos > 0) {
    			memcpy(in,src+srcpos,srcsize - srcpos);
    			strm.avail_in = srcsize - srcpos;
    			srcpos = srcsize;
    		} else {
    			break;
    		}
    
            strm.next_in = in;
    
            /* run inflate() on input until output buffer not full */
            do {
                strm.avail_out = CHUNK;
                strm.next_out = chunkBuf;
                ret = inflate(&strm, Z_NO_FLUSH);
                assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
                switch (ret) {
                case Z_NEED_DICT:
                    ret = Z_DATA_ERROR;     /* and fall through */
                case Z_DATA_ERROR:
                case Z_MEM_ERROR:
                    (void)inflateEnd(&strm);
                    return ret;
                }
    
                have = CHUNK - strm.avail_out;
                if (fwrite(chunkBuf, 1, have, dest) != have || ferror(dest)) {
                    (void)inflateEnd(&strm);
                    return Z_ERRNO;
                }
            } while (strm.avail_out == 0);
    
            /* done when inflate() says it's done */
        } while (ret != Z_STREAM_END);
    
        /* clean up and return */
    	(void)inflateEnd(&strm);
    
        return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
    }
    

    Er funktioniert auch soweit, außer dass

    strm.avail_out
    

    einen falschen Wert nach inflate() hat. 😕
    Ich habe die Funktion mit einem Buffer (size < CHUNK, natürlich mit deflate() gepackt, was ohne Probleme funktioniert hat) gestartet und in meiner Datei habe ich den ordentlich dekomprimierten Inhalt, nur folgen diesem lauter 0xCC bis die 16kB (CHUNK) geschrieben sind. D.h. es werden CHUNK bytes geschrieben, obwohl der out-Buffer gar nicht so viele hat nach der Dekomprimierung.

    Die innere Schleife wird zweimal durchlaufen, einmal ist

    strm.avail_out == 0
    

    beim zweiten Mal

    strm.avail_out == CHUNK
    

    Der File-Stream ist auf O_BINARY gesetzt.

    Ich komme irgendwie nicht auf den Fehler. Kann mir jemand helfen? 😞



  • Hat sich geklärt, bei der Komprimierung hat sich mir ein kleiner Fehler eingeschlichen. Der obige Code ist vollkommen richtig.


Anmelden zum Antworten