iPad - 解析一个非常巨大的json - 文件(50到100 mb之间)

时间:2013-04-10 17:26:34

标签: ios json ipad core-data bigdata

我正在尝试在iPad上解析一个非常大的json-File。文件大小将在50到100 MB之间变化(有一个初始文件,每月将有一个新的完整数据集,将被下载,解析并保存到coredata中)

我正在为一家公司构建这个应用程序作为企业解决方案 - json文件包含敏感的customerdata,它需要在ipad本地保存,以便它甚至可以脱机工作。当文件低于20mb时它工作,但现在数据集变得更大,我真的需要解析它。我在解析过程中收到内存警告,在第三次警告后它就崩溃了。 我有几个不同的核心数据实体,我只是设置来自json文件的所有值(第一次启动应用程序时),并且在完成所有操作后,我正在执行[context save]

我希望有人能就如何处理这些庞大的文件给我一些建议。我正在考虑将json文件拆分为几个较小的json文件,并且可能在多个线程中解析它们,但我不知道这是否是正确的方法。我想一个大问题是整个文件都被保存在内存中 - 也许有一些方法可以将它“流式化”到内存中或类似的东西?

我正在使用JSONKit(https://github.com/johnezang/JSONKit)来解析文件,因为我已经读过它是最快的一个(也许有一个较慢的一个在内存上更容易?)。

提前致谢。

2 个答案:

答案 0 :(得分:19)

1)将数据写入文件,然后使用NSData的 dataWithContentsOfFile:options:error:并指定 NSDataReadingMappedAlways NSDataReadingUncached 标志。这将告诉系统使用mmap()来减少内存占用,而不是用内存块加载文件系统缓存(这会使速度变慢,但对iOS的负担要小得多)。

2)您可以使用YAJL SAX style JSON parser在解码时获取对象。

注意:我没有做过2)但是已经使用了1)中体现的技术。

3)我自己最终需要这样的东西,写了SAX-JSON-Parser-ForStreamingData,可以绑定到任何异步下载器(包括我自己的)。

答案 1 :(得分:2)

考虑到移动设备当前的内存限制,可能无法解析100 MB的JSON文本,然后创建一个Foundation对象的表示,它本身的RAM大约是RAM的10倍。源JSON文本的大小。

也就是说,您的JSON结果将占用大约1 GB的RAM,以便分配基础对象所需的空间。

因此,无论您如何获取并读取和解析输入,都可能无法创建一个巨大的JSON表示。你需要将它分成许多较小的。但是,这可能需要在服务器端进行修改。

另一个解决方案是这个,但更详细说明:

使用SAX样式解析器,它通过流API将巨大的JSON作为输入,并输出几个较小的JSON文本(内部部分)。 SAX样式解析器可以使用Blocks API(调度lib)将其结果 - 较小的JSON异步传递给另一个JSON解析器。也就是说,较小的JSON被提供一个通常的JSON解析器,它生成JSON表示,然后由你的CoreData模型生成器提供。

您甚至可以下载巨大的JSON并使用SAX样式解析器同时解析它,同时创建更小的JSON并同时将它们存储到Core Data中。

你需要的是一个带有SAX样式API的JSON解析器,它可以解析输入文本块,执行速度快,并且可以创建Foundation对象的表示。

我只知道一个具有此功能集的JSON库,甚至还有一些示例可以部分显示如何完成这一点:GitHub上的JPJson。解析器也非常快 - 在ARM上它比JSONKit更快。警告:它的实现是用C ++实现的,需要几个步骤才能在开发者机器上安装它。不过,它有一个记录良好的Objective-C API。

想补充说我是作者;)很快就会有一个更新,它利用了最新的C ++ 11编译器和C ++ 11库特性,从而产生更快的代码(ARM上的速度比JSONKit快25%)是NSJSONSerialization的两倍。

给你同样的速度事实: 解析器能够下载(通过WiFi)并在7秒内在Wifi 802.11g上解析包含1000个JSON(每个25千字节)的25 MB数据,在Wifi 802.11n上解析4秒,包括在iPad 2上创建和发布1000个表示