一般而言,我们在Linux系统下通常使用解压缩命令去压缩/解压缩文件。在C++程序中,要实现该功能,我们有两种方式:
第一种方式操作起来很简便,但是它比较死板,以解压缩为例,就一定要将压缩包解压出来生成文件,再进行后续使用;而第二种方式,就比较灵活但是使用要求更高,比如考虑这样的场景:我们想在加压缩之后不生成文件直接使用,它的好处是能够省掉2次IO操作。由于第一种方式操作很简单,本文着重探讨如何利用第二种方式实现解压缩文件。
对于使用gzip压缩的文件,可以使用zlib库,但是zlib无法解压缩.zip文件。如果想要解压缩.zip文件,可以使用minizip库,或者7zip库。
这里我们使用https://github.com/Lecrapouille/zipper来实现:
Zipper is a C++11 wrapper around minizip compression library. Its goal is to bring the power and simplicity of minizip to a more object-oriented/c++ user-friendly library.
下载项目并编译:
1 2 3 4 5 |
|
最后一行命令输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
|
安装 C++ header files and compiled libraries, type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 |
|
For cmake:
1 2 3 4 5 6 7 |
|
如果不想通过FindPkgConfig的方式找到zipper库,可以使用如下的cmake配置:
1 2 3 |
|
其中include目录下放置Zipper-2.0.0里的内容(可以copy自/usr/include/Zipper-2.0.0)
然后创建lib文件夹,里面放入前面build文件夹里的动态库文件即可。(亲测有效)
-----------------------------------------------------------------------
补充:pkg-config介绍
pkg-config是一个在源代码编译时查询已安装的库的使用接口的计算机工具软件。
它输出已安装的库的相关信息,包括:
当安装一个库时(例如从RPM,deb或其他二进制包管理系统),会包括一个后缀名为pc的文件,它会放入某个文件夹下(Ubuntu系统中在/usr/lib/pkgconfig目录下):
比如,我们查看cuda-11.3.pc内容如下:
1 2 3 4 5 6 7 8 9 10 |
|
-----------------------------------------------------------------------
在测试方面,该项目引入了:
源码阅读:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
|
当我们运行C++代码时,遇到下列错误信息:
1 2 |
|
基本上根据信息判定,就是内存问题:
1. 内存重复释放,看程序中是否释放了两次空间(检查);
2. 内存越界(大部分是这种情况,如果你使用了数组,或者开辟了空间,但是在循环的时候越界了,就会出现这种情况);
Benchmark from sebastiandev/zipper#120 (作者不再维护该仓库,所以关闭了该ticket)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
后续会补充自己的测试结果...
下面是我自己写的解压到memory的封装函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
相关思考:
在测试时遇到了一个问题:
传入的压缩包里有40张图,在解压到第38张时,突然就断掉了,在该函数里也没有捕获任何异常(log如下):
问题解决了,是多线程的逻辑出了点问题。extractEntryToMemory和extractAll函数都测过了,没啥问题。