Ios 正在解码一个巨大的NSString,内存不足
我正在寻找如何改进使用base64编码解码40+MB NSString并将其保存到文件中的过程的想法,同时能够将该过程放入iPad1的256MB内存中 我从NSXMLParser获取NSString:Ios 正在解码一个巨大的NSString,内存不足,ios,xml,memory-management,base64,nsdata,Ios,Xml,Memory Management,Base64,Nsdata,我正在寻找如何改进使用base64编码解码40+MB NSString并将其保存到文件中的过程的想法,同时能够将该过程放入iPad1的256MB内存中 我从NSXMLParser获取NSString: id pointerToString; - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{ if ([currentElement isEqualToString:@"myElement"])
id pointerToString;
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
if ([currentElement isEqualToString:@"myElement"])
{
pointerToString = [string retain];
}
}
然后我在回调中使用pointerToString:
[handler performSelector: action withObject: pointerToString];
在回调函数中(id值是指针列表)。我使用pointerToString初始化NSData,同时使用base64编码对其进行解码
^(id value)
{
if ( [[value class] isSubclassOfClass:[NSString class]] )
{
NSData *data = [NSData dataFromBase64String:value];
[data writeToFile:file.path atomically:YES];
}
}
iPad1设备内存不足,在NSData呼叫后或期间内存分配达到130MB左右时,会被iOS杀死
我已经确定,为了以这种方式处理40+MB的NSString,我需要大约180+MB的RAM(这是iPad2和iPad3上的最大内存分配,因为内存更多,所以这个过程有效)
有什么想法/建议吗
谢谢你的方法
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
可能不会同时接收所有数据。
医生说
“由解析器对象发送,以向其委托提供表示当前元素的全部或部分字符的字符串。”
所以它被称为多次。
看起来您正在尝试一次写入整个字符串(如果我错了,很抱歉)。
因此,您可以通过执行以下操作将接收到的数据附加到文件中:
您可以使用以下选项的组合:
-writeData:
及
用于将NSData写入文件末尾的NSFileHandle类中的方法
但在部分数据接收时请小心使用base64编码 编辑:
在处理这种大小的文件时,您可能不希望一次在内存中加载整个数兆字节的文件,无论是巨大的输入文件还是几乎同样巨大的输出文件。您应该以流式方式对此进行解析,在执行过程中对foundCharacters
中的数据进行解码,而不是在内存中保留任何重要部分
但是,传统技术可能会在流程的三个阶段保存整个XML文件内存:
NSXMLParser
,以及不太熟悉的LibXML
解析器。NSXMLParser
的问题是,在开始解析之前,它会将整个XML文件加载到内存中,即使您使用initWithContentsOfURL
在我之前的回答中,我错误地宣称,通过使用initWithContentsOfURL
,NSXMLParser
可以在下载URL内容时将其解析为漂亮的小数据包。NSXMLParserDelegate
协议的foundCharacters
方法似乎与NSURLConnectionDelegate
方法didReceiveData
非常相似,我确信NSXMLParser
将像NSURLConnection
一样处理流,即在下载过程中返回信息。可悲的是,事实并非如此
不过,通过使用LibXML
,就像Apple XMLPerformance示例项目一样,您实际上可以使用流媒体的NSURLConnection
功能,从而动态解析XML
我已经创建了一点,但我可能建议您详细了解一下Apple的XMLPerformance示例项目。但在我的实验中,一个56mb的XML文件在通过NSXMLParser
解析和转换时消耗的内存远远超过100mb,但在使用LibXML2
时仅消耗2mb
在您的评论中,您描述了将Base64编码的数据下载到文件中,然后对其进行解码的愿望。这种方法似乎效率要低得多,但肯定能奏效。顺便说一句,在最初的下载中,您有相同的内存问题(我在上面解决了)。我敦促您确保Base64编码数据的初始下载不会像大多数例程一样轻松地加载到RAM中。假设您使用的是
NSURLConnection
,您希望在didReceiveData
中接收数据时,将数据写入NSOutputStream
,而不是将其保存在RAM中
请参阅苹果公司AdvancedGetController.m中的
didReceiveResponse
,了解如何在接收文件时编写文件,而不是将其添加到NSMutableData
中的典型模式(因为这些例程中的大多数都假设您正在处理大小合理的文件)。(忽略AdvancedURLConnections示例中有关身份验证等的所有内容,但重点了解它是如何写入NSOutputStream
的。)此技术将解决此答案顶部列出的三个问题中的第一个问题,而不是后两个问题。为此,您必须考虑使用苹果的XMLPerformance示例项目中说明的LibXML2
,或其他类似技术。我不知道,但这是一个很好的问题。但是,我想知道为什么您有这么大的NSString?修改base64编码,以便在您从解析器接收字符时将其解码到文件中。关键字:“流”(整个过程中,还包括删除NSData
的全部内存使用)看起来您实际上正在尝试解码base64字符串。您通常有大约140mb的RAM fre
-seekToEndOfFile