当前位置: 首页 > 知识库问答 >
问题:

LZMA SDK解压缩iOS(xcode)使用过多RAM

范嘉
2023-03-14

我正在尝试在iPhone/iPad应用程序中使用LZMA SDK,我的起点是Mo Dejong提供的iPhone LZMA示例项目,可在此获得:https://github.com/jk/lzmasdk原文是:http://www.modejong.com/ios/lzmasdk.zip(我两个都试了,结果都一样)。

问题是,提取所使用的RAM与.7z未压缩的内存一样多。换句话说,假设我有一个40MB的压缩文件,未压缩的文件是一个大约250MB的二进制sqlite DB,当它将文件解压到250MB时,它会慢慢地消耗越来越多的内存。这将导致iPad1或iPhone4之前的任何设备崩溃(256MB内存)。我有一种感觉,很多人最终会遇到同样的问题,所以现在的解决方案可以帮助很多开发人员。

我最初使用基于windows的7-zip(最新版本)和16MB字典大小在PC上创建了.7z文件。它应该只需要18MB的RAM就可以解压缩(在PC上测试任务管理器时就是这样)。我还尝试使用keka(开源mac存档器)创建存档,但它没有解决任何问题,尽管我可以确认keka本身在mac上提取文件时只使用了19MB的ram(这是我所期望的)。我想下一步是将Keka的源代码与LZMA SDK的源代码进行比较。

在创建.7z文件时,我使用了不同的字典大小和其他设置,但没有任何帮助。在压缩之前,我还尝试将单个二进制文件拆分成24个较小的部分,但这也于事无补(仍然使用超过250MB的RAM来提取这24个部分)。

注意,我对原始代码所做的唯一更改是使用了一个更大的.7z文件。还要注意,它确实会在提取完成后立即释放RAM,但这没有帮助。我觉得它并没有像它应该做的那样释放RAM,或者它把整个内容放入RAM,直到它完成的最后,然后才把它从RAM中移出来。此外,如果我尝试使用mac应用程序提取相同的文件,同时运行仪器,我不会看到相同的行为(例如,StuffIt Expander在提取文件时达到了60MB左右的RAM;开源mac存档程序Keka在提取文件时达到了19MB的RAM)。

我并不是一个Mac/Xcode/Objective-C开发人员(还没有),因此我将非常感谢任何有关这方面的帮助。我可以使用zip或rar来代替,但使用LZMA可以得到更好的压缩,所以如果可能的话,我想坚持使用这个解决方案,但显然我需要使它工作而不崩溃。

谢谢!

共有1个答案

童冠玉
2023-03-14

7zip的作者Igor Pavlov给我发了电子邮件,他基本上说我在原问题中提出的意见是SDK的c版本的一个已知限制。C++版本没有这个限制。实际报价:

“7-zip使用另一个用C++编写多线程解码器。C++.7z解码器不需要为整个实体块分配RAM块。请同时阅读此线程:

http://sourceforge.net/projects/sevenzip/forums/forum/45797/topic/5655623“

因此,在有人修复iOS的SDK之前,解决方法是:

1)决定您希望对文件解压缩操作有多大RAM限制。

2)档案中任何一个文件超过了以上1的限制,都必须进行拆分,您可以使用任何二进制拆分器应用程序(如splits:http://www.fourmilab.ch/splits/)进行拆分

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];
    }
 类似资料:
  • 问题内容: 我知道这是一项容易的任务,但是更改代码后它停止工作,并且无法恢复!我实际上使用了两个函数来进行压缩和解压缩,尽管实际上它是“ jar”和“ unjar”,但这并没有太大的区别 任何帮助/建议吗? 创建JarFile时发生错误: 问题答案: 我不知道这是否是您的问题,但是通常最好在完成写入后关闭每个zip条目。 请参阅。 在显示的代码中,不会关闭邮政编码中的最后一个条目。您也不会显示关闭

  • 我通常使用压缩,使用解压(由于习惯使用gzip)。 我最近得到了一个带有超线程的四核CPU,所以我有8个逻辑核,我注意到许多核在压缩/解压过程中没有使用。 有什么方法可以利用未使用的内核来加快速度吗?

  • tar [-]c|x|u|r|t[z|j][v] -f 归档文件 [待打包文件] 将多个文件打包为一个归档文件,可以在打包的同时进行压缩。支持的格式为 tar(归档)、gz(压缩)、bz2(压缩率更高,比较耗时) 操作选项 -c 创建 -x 解包 -u 更新 -r 添加 -t 查看 -d 比较压缩包内文件和文件 -A 将 tar 文件添加到归档文件中 格式选项 -z 使用 gz 压缩格式 -j 使

  • 问题内容: 有人可以向我解释zlib库在Nodejs中如何工作吗? 我对Node.js很陌生,还不确定如何使用缓冲区和流。 我的简单情况是一个字符串变量,我想将字符串压缩或解压缩(压缩或膨胀,gzip或gunzip等)到另一个字符串。 即(我希望它如何工作) 感谢您的帮助:) 问题答案: 更新 :没意识到在节点0.5中有一个新的内置“ zlib”模块。我在下面的答案是针对第三方node- zlib

  • 常用压缩包—解压—令整理 Linux 后缀为 .war 格式的文件(一般用在部署 Tomcat 项目的时候) 命令:unzip -oq XXXXXX.war -d ROOT 如果没有 ROOT 目录会自动创建 ROOT 目录。 Linux 后缀为 .tar.gz 格式的文件-解压 命令:tar zxvf XXXXXX.tar.gz Linux 后缀为 .bz2 格式的文件-解压 命令:bzip2

  • 问题内容: 在许多在线示例中,使用编码缓冲区在Java中对文件进行(解压缩)。但是,使用NIO时,无需选择合适的缓冲区大小。我找到了文件和套接字的示例,但是是否有NIO通道用于压缩输入(例如),因此您可以使用它代替自己创建缓冲区吗? 问题答案: 不,专业的ZIP频道尚不存在…我想您可以执行以下操作。使用NIO读取要缓冲的任何通道。然后检索刚刚从缓冲区读取的字节到字节数组,使用ByteArrayIn