使用 GZIP 或 deflate 压缩/解压 Objective-C (iphone) 中的 NSString
-
26-09-2019 - |
题
我有一个在 Windows Azure 上运行的 Web 服务,它返回我在 iPhone 应用程序中使用的 JSON。
不幸的是,Windows Azure 似乎还不支持动态响应的压缩(说来话长),所以我决定通过返回一个未压缩的 JSON 包来解决这个问题,其中包含一个压缩的(使用 GZIP)字符串。
例如
{"Error":null,"IsCompressed":true,"Success":true,"Value":"vWsAAB+LCAAAAAAAB..etc.."}
...其中 value 是以 JSON 表示的复杂对象的压缩字符串。
这在服务器上实现起来非常容易,但是对于我来说,我无法弄清楚如何将 gzipped NSString 解压缩为未压缩的 NSString,我可以找到的 zlib 等的所有示例都在处理文件等。
谁能给我任何关于如何做到这一点的线索?(我也很高兴有一个使用 deflate 的解决方案,因为我可以更改服务器端实现以也使用 deflate)。
谢谢!!
史蒂文
编辑1: 啊啊,我看到 ASIHTTPRequest 在其源代码中使用以下函数:
//uncompress gzipped data with zlib
+ (NSData *)uncompressZippedData:(NSData*)compressedData;
...我知道我可以将 NSString 转换为 NSData,所以我会看看这是否会引导我到任何地方!
编辑2: 不幸的是,编辑 1 中描述的方法并没有引导我到任何地方。
编辑3: 根据下面有关 Base64 编码/解码的建议,我想出了以下代码。您可以猜到,encodedGzippedString 是一个字符串“Hello,我的名字是 Steven Elliott”,它被 gzip 压缩,然后转换为 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);
解决方案
经过这么长时间,我终于找到了解决这个问题的方法!
上面的答案都没有帮助我,尽管它们看起来都很有希望。最后,我能够使用 .net 的 chilkat 框架通过 gzip 压缩服务器上的字符串......然后在 iPhone 上使用 iOS 的 chilkat 框架解压它(尚未发布,但如果你直接给他发电子邮件就可以使用)。
chilkat 框架使这一切变得超级容易,所以对开发人员竖起大拇指!
其他提示
您的“压缩”字符串不是原始的 GZIP 数据,它采用某种编码,允许将这些字节存储在字符串中 - 看起来像 base-64 或类似的东西。要从中获取 NSData,您需要将其解码为 NSData。
如果它确实是 base-64,请查看此博客文章附带的代码:http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html这会做你想做的事。
一旦您拥有 NSData 对象,ASIHTTPRequest 方法可能会按照您的意愿执行。
这对我有用:从字符串Gzipeed,然后从编码UN-GZPRICKENT字符串(ALL UTF8)编码的base64。
#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