使用GZIP或deflate在objective-c (iphone)中压缩/解压缩NSString

8

我有一个运行在Windows Azure上的Web服务,返回JSON数据供我的iPhone应用程序使用。

不幸的是,Windows Azure似乎还不支持动态响应的压缩(长话短说),所以我决定通过返回一个未压缩的JSON包含经过GZIP压缩的字符串来解决这个问题。

例如:

{"Error":null,"IsCompressed":true,"Success":true,"Value":"vWsAAB+LCAAAAAAAB..etc.."}

...其中的value是以JSON表示的一个复杂对象的压缩字符串。

在服务器上实现这个功能真的很容易,但我却无法想出如何将gzip压缩的NSString解压成未压缩的NSString,我能找到的所有关于zlib等的示例都是处理文件等。

有人可以给我一些提示吗?(如果使用deflate也可以,因为我可以更改服务器端的实现来使用deflate)

谢谢!

Steven

编辑1: 啊,我看到ASIHTTPRequest在其源代码中使用了以下函数:

//uncompress gzipped data with zlib
+ (NSData *)uncompressZippedData:(NSData*)compressedData;

我知道可以将NSString转换为NSData,所以我会尝试一下这个方法!

编辑2:不幸的是,编辑1中描述的方法并没有帮助我。

编辑3:根据下面有关base64编码/解码的建议,我编写了以下代码。 encodedGzippedString是一个字符串“Hello, my name is Steven Elliott”,它被压缩并转换为base64字符串。不幸的是,使用NSLog打印的结果为空。

NSString *encodedGzippedString = @"GgAAAB+LCAAAAAAABADtvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee++997o7nU4n99//P1xmZAFs9s5K2smeIYCqyB8/fnwfPyK+uE6X2SJPiyZ93eaX+TI9Lcuiatvx/wOwYc0HGgAAAA==";
NSData *decodedGzippedData = [NSData dataFromBase64String:encodedGzippedString];
NSData* unGzippedJsonData = [ASIHTTPRequest uncompressZippedData:decodedGzippedData];   
NSString* unGzippedJsonString = [[NSString alloc] initWithData:unGzippedJsonData encoding:NSASCIIStringEncoding];       
NSLog(@"Result: %@", unGzippedJsonString);  
4个回答

4
经过这么长时间,我终于找到了解决这个问题的方法!
以上所有的答案都没能帮到我,尽管它们看起来很有希望。最终,我使用chilkat框架在服务器上对字符串进行gzip压缩...然后在iPhone上使用chilkat框架进行解压缩(尚未发布,但如果您直接联系该人,就可以获得)。
chilkat框架使这变得超级简单,所以开发者点赞!

你好,你能提供框架的确切链接吗? - Dunes Buggy

1

你的“压缩”字符串不是原始的GZIP数据,它采用了一些编码方式,使得这些字节可以存储在字符串中--看起来像是base-64或类似的东西。要从中获取NSData,你需要将其解码为NSData。

如果它真的是base-64,请查看这篇博客文章和相关代码: http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html 它会做你想要的事情。

一旦你有了一个NSData对象,ASIHTTPRequest方法可能会按照你的意愿进行操作。


嗨Quixoto,感谢你的回复。如果您查看我的原始帖子中的第3次编辑,您将看到在尝试了您的建议后发生了什么。再次感谢! - Steven Elliott
这是一个合理的步骤集,但不清楚的是:传输的字符串肯定是Base64吗?(很可能)在Windows领域中,原始字符串的原始编码是什么?您正在选择解码时的ASCII编码,这不太可能是正确的。NSData缓冲区中的数据是否有所提示? - Ben Zotto

0
这对我有用: 从一个字符串gzipeed,然后base64编码 到未压缩的字符串(全部utf8)。
#import "base64.h"
#import "NSData+Compression.h"

...

+(NSString *)gunzipBase64StrToStr:(NSString *)stringValue {
    //now we decode from Base64
    Byte inputData[[stringValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];//prepare a Byte[]
    [[stringValue dataUsingEncoding:NSUTF8StringEncoding] getBytes:inputData];//get the pointer of the data
    size_t inputDataSize = (size_t)[stringValue length];
    size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);//calculate the decoded data size
    Byte outputData[outputDataSize];//prepare a Byte[] for the decoded data
    Base64DecodeData(inputData, inputDataSize, outputData, &outputDataSize);//decode the data
    NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];//create a NSData object from the decoded data
                                                                                      //NSLog(@"DATA: %@ \n",[theData description]);

    //And now we gunzip:
    theData=[theData gzipInflate];//make bigger==gunzip
    return [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
}

@end

0

我需要使用Objective-C在iPhone上压缩数据,并在PHP上解压缩。以下是我在XCode 11.5和iOS 12.4中使用的方法:

iOS Objective-C压缩解压测试 在Build Phases -> Link Binary With Library中包含libcompression.tbd。然后包含头文件。

#include "compression.h"


NSLog(@"START META DATA COMPRESSION");
NSString *testString = @"THIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TEST";
NSData *theData = [testString dataUsingEncoding:NSUTF8StringEncoding];
size_t src_size = theData.length;
uint8_t *src_buffer = (uint8_t*)[theData bytes];
size_t dst_size = src_size+4096;
uint8_t *dst_buffer = (uint8_t*)malloc(dst_size);
dst_size = compression_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL, COMPRESSION_ZLIB);
NSLog(@"originalsize:%zu compressed:%zu", src_size, dst_size);
NSData *dataData = [NSData dataWithBytes:dst_buffer length:sizeof(dst_buffer)];
NSString *compressedDataBase64String = [dataData base64EncodedStringWithOptions:0];    

NSLog(@"Compressed Data %@", compressedDataBase64String);

NSLog(@"START META DATA DECOMPRESSION");
src_size = compression_decode_buffer(src_buffer, src_size, dst_buffer, dst_size, NULL, COMPRESSION_ZLIB);
NSData *decompressed = [[NSData alloc] initWithBytes:src_buffer length:src_size];
NSString *decTestString;
decTestString = [[NSString alloc] initWithData:decompressed encoding:NSASCIIStringEncoding];

NSLog(@"DECOMPRESSED DATA %@", decTestString);

free(dst_buffer);

在 PHP 方面,我使用了以下函数来解压数据:
function decompressString($compressed_string) {

    //NEED RAW GZINFLATE FOR COMPATIBILITY WITH IOS COMPRESSION_ZLIB WITH IETF RFC 1951
    $full_string = gzinflate($compressed_string);
    return $full_string;

}  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接