https://github.com/jk/lzmaSDK
原文在这里: http://www.modejong.com/iOS/lzmaSDK.zip
(我试过了两次,我从两者得到了相同的结果).
问题是提取使用的内存与.7z包含未压缩的RAM一样多.换句话说,假设我有一个40MB的压缩文件,未压缩的文件是一个大约250MB的二进制sqlite DB,它将慢慢耗尽越来越多的内存,因为它将文件解压缩到250MB.在iPhone4(256MB RAM)之前,这会使iPad1或任何东西崩溃.我有一种感觉很多人最终会遇到同样的问题,所以现在解决方案可以帮助很多开发人员.
我最初使用基于Windows的7-zip(最新版本)和16MB字典大小在PC上创建.7z文件.它应该只需要18MB的RAM来解压缩(在PC上查看任务管理器时就是这种情况).我也尝试使用keka(开源mac archiver)创建存档,它没有解决任何问题,虽然我可以确认keka本身在Mac上提取文件时只使用19MB的ram,这是我所期望的.我想下一步是将Keka的源代码与LZMA SDK的源代码进行比较.
在创建.7z文件时,我使用不同的字典大小和其他设置,但没有任何帮助.我还尝试在压缩之前将我的单个二进制文件拆分为24个较小的部分,但这也没有帮助(仍然使用超过250MB的RAM来提取24个部分).
请注意,我对原始代码所做的唯一更改是使用更大的.7z文件.另请注意,一旦提取完成,它会立即释放RAM,但这没有用.我觉得它不会释放RAM,因为它提取它应该如此,或者它将整个内容放入RAM直到最后完成并且只是将它移出RAM.此外,如果我尝试使用mac应用程序提取相同的文件,在运行仪器时,我看不到相同的行为(StuffIt Expander例如在提取文件时最大约为60MB RAM,Keka,开源mac archiver最大容量为19MB RAM).
我不是一个mac / xcode / objective-c开发人员(还),所以对此的任何帮助将不胜感激.我可以使用zip或rar代替,但是我用LZMA得到了更好的压缩,所以如果可能的话我想坚持使用这个解决方案,但显然我需要让它工作而不会崩溃.
谢谢!
解决方法
“7-Zip使用另一个用C编写的多线程解码器.C.7z解码器不需要为整个实体块分配RAM块.另请阅读此线程:
http://sourceforge.net/projects/sevenzip/forums/forum/45797/topic/5655623
“
因此,在有人修复SDK for iOS之前,解决方法是:
1)确定要对文件解压缩操作使用的RAM限制.
2)存档中任何超过上述限制的SINGLE文件必须拆分,您可以使用任何二进制拆分器应用程序(如拆分)执行此操作:
http://www.fourmilab.ch/splits/
3)文件准备好后,使用MoDJ在他的答案中描述的字典/块大小选项创建7z文件,例如24 meg限制:
7za a -mx = 9 -md = 24m -ms = 24m CompressedFile.7z SourceFiles *
4)在iOS应用程序中,解压缩文件后,确定已拆分的文件,并将它们重新连接在一起.这个代码并不是那么复杂(我假设splits.exe使用的命名约定,即file.001,file.002等)
if(iParts>1) { //If this is a multipart binary split file,we must combine all of the parts before we can use it NSString *finalfilePath = whateveryourfinaldestinationfilenameis NSString *splitfilePath = [finalfilePath stringByAppendingString:@".001"]; NSFileHandle *myHandle; NSFileManager *fileManager = [NSFileManager defaultManager]; NSError *error; //If the target combined file exists already,remove it if ([fileManager fileExistsAtPath:finalfilePath]) { BOOL success = [fileManager removeItemAtPath:finalfilePath error:&error]; if (!success) NSLog(@"Error: %@",[error localizedDescription]); } myHandle = [NSFileHandle fileHandleForUpdatingAtPath:splitfilePath]; NSString *nextPart; //Concatenate each piece in order for (int i=2; i<=iParts; i++) { //Assumes fewer than 100 pieces if (i<10) nextPart = [splitfilePath stringByReplacingOccurrencesOfString:@".001" withString:[NSString stringWithFormat:@".00%d",i]]; else nextPart = [splitfilePath stringByReplacingOccurrencesOfString:@".001" withString:[NSString stringWithFormat:@".0%d",i]]; NSData *datapart = [[NSData alloc] initWithContentsOfFile:(NSString *)nextPart]; [myHandle seekToEndOfFile]; [myHandle writeData:datapart]; } [myHandle closeFile]; //Rename concatenated file [fileManager moveItemAtPath:splitfilePath toPath:finalfilePath error:&error]; }