1

ObjectiveZlibサンプル コードの dataByDecompressingData: メソッドを使用して、いくつかの zlib データを解凍しようとしています。これは、c++ の代わりに Objective-c で使用するように変換するのに役立ちました。以下のコード

- (NSData*) dataByDecompressingData:(NSData*)data{
    Byte* bytes = (Byte*)[data bytes];
    NSInteger len = [data length];
    NSMutableData *decompressedData = [[NSMutableData alloc] initWithCapacity:COMPRESSION_BLOCK];
    Byte* decompressedBytes = (Byte*) malloc(COMPRESSION_BLOCK);

    z_stream stream;
    int err;
    stream.zalloc = (alloc_func)0;
    stream.zfree = (free_func)0;
    stream.opaque = (voidpf)0;

    stream.next_in = bytes;
    err = inflateInit(&stream);
    CHECK_ERR(err, @"inflateInit");

    while (true) {
        stream.avail_in = len - stream.total_in;
        stream.next_out = decompressedBytes;
        stream.avail_out = COMPRESSION_BLOCK;
        err = inflate(&stream, Z_NO_FLUSH);
        [decompressedData appendBytes:decompressedBytes length:(stream.total_out-[decompressedData length])];
        if(err == Z_STREAM_END)
            break;
        CHECK_ERR(err, @"inflate");
    }

    err = inflateEnd(&stream);
    CHECK_ERR(err, @"inflateEnd");

    free(decompressedBytes);
    return decompressedData;
}

これが実行されると、Z_BUF_ERROR が表示されます。ASIHTTPReqest を参照していることはわかっています、xcode が提供する同じ zlib クラスを使用して解凍している可能性があると考えています。スペースが原因でファイルの解凍を処理できます。

これが正しいかどうかは完全にはわかりません.2つの解決策を提供しました. Aさん、どうしたらいいの?B、より良い第 3 の選択肢はありますか?

どんな助けでも大歓迎です。

4

1 に答える 1

2

http://www.zlib.net/zlib_how.htmlを参照してください。

Z_BUF_ERROR については後で詳しく説明しますが、これは単純に、inflate() がこれ以上入力を消費したり出力を生成したりできなかったことを示しているだけで十分です。inflate() は、より多くの出力スペースまたはより多くの利用可能な入力で再度呼び出すことができます。これは、このコードで行われます。

私が見るエラーのいくつか:

1/ を設定するたびに、 もstream.next_in設定する必要がstream.avail_inあります。stream.avail_in入力の次のチャンクを与えていないときは、変更しないでください。avail_in電話をかける前にイニシャルを設定するinflateInitことをお勧めします。

2/ を使用inflateInit2(&stream, -MAX_WBITS)するのは良い考えかもしれません。の通常のバージョンでinflateInitは、データの圧縮タイプ (gzip または zlib) がチェックされないことに注意してください。gzip を選択すると、解凍に失敗します。

(動作するはずで、テストなしで書かれています)

-(NSData*)decompressData:(NSData*)compressedData {
    z_stream stream;

    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;

    //we set the input, no need to change the values later
    stream.next_in = (Bytef *) [compressedData bytes];
    stream.avail_in = compressedData.length;  

    int result = inflateInit2(&stream, -MAX_WBITS);

    if (result != Z_OK) {
        return nil;
    }

    NSMutableData* uncompressedData = [NSMutableData data];
    //make buffer big enough - 128KB
    int bufferLength = 128 * 1024;
    char *buffer = malloc(bufferLength);

    while (true) {
        stream.next_out = buffer;
        stream.avail_out = bufferLength;

        //calling with Z_FINISH because we already have all the input
        result = inflate(&stream, Z_FINISH);

        if (result != Z_OK && result != Z_STREAM_END) {
             inflateEnd(&stream);
             free(buffer);
             return nil;
        }

        [uncompressedData appendBytes:buffer length:(bufferLength - stream.avail_out)];

        if (result == Z_STREAM_END) {
            break;
        }
    }


    inflateEnd(&stream);
    free(buffer);

    return uncompressedData;
}
于 2012-12-13T21:09:55.813 に答える