Linux C语言 Zlib 实现解压zip文件

Linux C语言 Zlib 实现解压zip文件

因为在做嵌入式Linux,做OTA功能的时候需要解压zip升级包。所以需要用到zip文件的解压缩功能。

就想着能不能用zlib来完成这个功能。在网上一通找以后,发现教程千篇一律,要么是打着解压文件的标题解压buff内容,要么是c++完成的。好不容易有两篇C语言解压zip文件的,结果并不能用。

最后还是只能看英文文档,终于找到案例了。下面记录如何实现的,其实还是非常的简单,例程写得比较复杂,我只用到一个解压功能,我只修改了一点代码,没有太大改动。有需要的话,可以再进行精简。上流程:

1. 安装zlib库

下载zlib。下载zlib source code,官网能直接下载,也可以去github上下载。

解压编译安装zlib。

$ tar -xzvf zlib-1.2.11.tar.gz
$ cd zlib-1.2.11
$ ./configure
$ make
$ sudo make install
$ pkg-config zlib --libs --cflags
>> -I/usr/local/include  -L/usr/local/lib –lz

安装成功。

2. 使用minizip

上面的源码目录contrib\minizip即为minizip,是zipunzip功能最小化实现。

打开Makefile文件,我们可以看到,这个目录下最终编译出来两个工具,一个是miniunz,一个是minizip。一个是zip的解压缩工具,一个文件的zip压缩工具。

CC=cc
CFLAGS=-O -I../..

UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
ZIP_OBJS = minizip.o zip.o   ioapi.o ../../libz.a

.c.o:
	$(CC) -c $(CFLAGS) $*.c

all: miniunz minizip

miniunz:  $(UNZ_OBJS)
	$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)

minizip:  $(ZIP_OBJS)
	$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)

test:	miniunz minizip
	./minizip test readme.txt
	./miniunz -l test.zip
	mv readme.txt readme.old
	./miniunz test.zip

clean:
	/bin/rm -f *.o *~ minizip miniunz

接下来对这个目录进行编译。

$ ./configure
$ make clean
$ make

经过编译,目录下能得到上面的两个工具。我们根据Makefile中的test的使用方法对两个工具进行使用。

$ echo "hello world!" > test.txt
$ ./minizip test.zip test.txt
# 可以看到一个目录下生成了test.zip
$ ./miniunz -l test.zip
# 可以看到压缩包的各种信息。打包压缩比,里面包含的文件等。
$ rm -r test.txt
$ ./miniunz test.zip
$ ls
# 好了,解压后,目录下的test.txt又出现了。

在这里插入图片描述
这里我们试一下用zip工具压缩test.txt,看看miniunz是否能够解压成功。

$ sudo apt install zip
$ rm test.zip
$ zip -o test.zip test.txt
$ ./miniunz test.zip

OK! 实践证明,代码是有没有问题。

这里解释一下,加-l参数是只读取信息,不提取文件。
不加参数就是提取文件。压缩包里有多少文件就提取多少文件。可以通过在提供一个参数名,即压缩包内文件的文件名,可以直接只提取到对应的文件,如 ./miniunz test.zip test.txt。加-d path可以指定提取文件的输出路径。

这些参数的用法可以打开miniunz.c进行查看。
如此完善的解压功能,代码本身可以直接拿来用,不过稍微有点臃肿,可以自己进行删减。

3. 修改miniunz.c

从上面的Makefile可以看出,编译我们需要的功能仅仅只需要gcc -O -I../.. -o miniunz miniunz.c unzip.o ioapi.o ../../libz.a。即只需要unzip.cioapi.c文件,以及我们的自己的解压代码,还有zlib库。

这里我们需要修改miniunz.c,事实上,这个文件里面的api基本上能直接拿来用。因为我只需要解压缩文件,并且我要解压的压缩包内只有一个文件,所以,我修改了一些代码。

$ touch demoUnzip.c

把需要的内容从miniunz.c复制到我们的文件中。这里我把main()改成了下面的代码,仅仅只保留解压缩一个文件的功能。

$ gcc -O -I../.. -o demoUnzip demoUnzip.c unzip.o ioapi.o ../../libz.a

运行验证,结果完美。☺☺☺

在这里插入图片描述

int ch_unzip_file(char *zipFileName, char *srcPath, char *obFileName, char *obPath)
{
    if (zipFileName == NULL || obFileName == NULL)
    {
        return -1;
    }

    unzFile uf = NULL;
    char filename_try[MAXFILENAME + 16] = "";
    int opt_do_extract_withoutpath = 0;
    int opt_overwrite = 0;
    int ret_value = 0;
    const char *password = NULL;
    char zipFile[64] = {0};
    strcat(zipFile, srcPath);
    strcat(zipFile, zipFileName);

#ifdef USEWIN32IOAPI
    zlib_filefunc64_def ffunc;
#endif

    strncpy(filename_try, zipFile, MAXFILENAME - 1);
    /* strncpy doesnt append the trailing NULL, of the string is too long. */
    filename_try[MAXFILENAME] = '\0';

#ifdef USEWIN32IOAPI
    fill_win32_filefunc64A(&ffunc);
    uf = unzOpen2_64(zipFile, &ffunc);
#else
    uf = unzOpen64(zipFile);
#endif
    if (uf == NULL)
    {
        strcat(filename_try, ".zip");
#ifdef USEWIN32IOAPI
        uf = unzOpen2_64(filename_try, &ffunc);
#else
        uf = unzOpen64(filename_try);
#endif
    }

    if (uf == NULL)
    {
        printf("Cannot open %s or %s.zip\n", zipFile, zipFile);
        return 1;
    }
    printf("%s opened\n", filename_try);

    ret_value = do_extract_onefile(uf, obFileName, opt_do_extract_withoutpath, opt_overwrite, password);

    unzClose(uf);

    return ret_value;
}

int main(int argc, char *argv[])
{

    ch_unzip_file(argv[1], "", argv[2], "");

    return 0;
}

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值