原文:http://blog.octo.com/en/category/it-architects-workshop|
问题的提出
为什么要untar?
手机 app 中网络连接需要耗费一定的时间。与下载10个1M的小文件相比,一次性下载1个10M的文件显然可以得到性能上的极大提升。
unix 下有一个 tar 命令无人不知。
tar 命令的用途正如维基百科中所说:通常用于将多个文件打包成一个较大的文件,以用于分发和存档的目的。打包之后保留所有的文件系统信息,诸如用户和组权限,日期、以及原来的目录结构。
这正是我们使用tar 的目的。
那么,在 iOS 设备上,如何将一个tar 包 untar(解开)呢?
如何解包?
通过 google 搜索,得知 iOS 提供两种解包的方法:
为什么不使用 libarchive?
如果使用 libarchive:
有没有其他办法?我的 app 是肯定要在 AppStore上架的,而且我也不想在我的app 中链接 4.7 M 之巨的难于维护的代码。我决定自己实现一个轻量级的 untar 工具。
怎么做?
Libarchive 编译后有4.7M,但其中许多东西我们并不需要。
我们仅仅需要其中 untar(解包)功能,但下列功能却不需要 :
解决之道
什么是tar 文件?
tar 文件是由一个个 512 字节的块构成的。
第一个文件的头构成了第一个块,然后是文件内容,然后是新的文件头,新的文件内容。
如下图所示:(H 表示头块,C表示内容块,/ 表示不完全的内容块)
H C C C C C C C C / HC C C C / H H C C C C C C / _ _
在tar 文件最后有两个空块。每个文件总是从整数块开始。有的文件没有内容块(例如文件夹)。每个块都是512字节。
头块中包含许多数据,绝大多数数据对于我们来说是无意义的,我们仅仅需要:
FileName |
|
Size |
|
Type |
|
通过文件尺寸,我们可以知道下一个文件的头块位于什么位置,以及文件最后一个内容块是哪里。
成果:轻量级的 iOS Untar
够简单的,不是吗?我用 O-C 实现了它,然后放到了 github:https://github.com/mhausherr/Light-Untar-for-iOS
代码基于 BSD 协议,你可以在自己的项目里使用它。
是不是比 libarchive 更酷?轻量级的 iOS Untar 仅仅2 个文件,168 行代码,包括注释行和许可声明。
使用方法是包含 .h 文件然后利用 NSFileManager 的createFilesAndDirectoriesAtPath 方法:
1 |
[[NSFileManager defaultManager] createFilesAndDirectoriesAtPath:@"/path/to/your/extracted/files/" withTarData:tarData error:&error]; |
tarData 是一个 NSData 对象。你可以用这样来创建它:
1 |
NSData *tarData = [NSData dataWithContentsOfFile:@"/path/to/your/tar/file.tar"]; |
性能和安全限制
性能
Libarchive 采用 c 语言编写,当然要比我用 O-C 代码实现要快。
问题是:对于你来说什么更重要?
如果是后者,轻量级的 iOS Untar更适合你。
安全
对于 tar 包来说主要的安全问题是什么?
这些问题在我的代码中都不存在,你可以安全地使用它。
你要知道,它是一个 iOS 库。在 iOS 中,程序在沙盒中运行,系统自身会保证代码的安全性,我们完全不需要做任何事情。
结论
手机应用主要是在低性能设备是运行的。app 编译尺寸非常重要。
如果你需要解决一个简单的问题,首先考虑什么方式最好:一个庞大的框架当然可以为你解决问题。但你真需要这个框架的全部功能吗?还是仅仅需要其中某个功能?