c++ linux压缩文件及解压缩,用到的库为zip。
https://github.com/nih-at/libzip/tree/v1.9.2
运行脚本build.sh,在build下会生成ziplib库,运行程序时引用,也可直接装入系统中。
rm -rf build
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=ziplib ..
make
make install
头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include "unistd.h"
#include <zip.h>
#define DBG_SEQ 0
#define LOGI printf
#define LOGD printf
#define LOGE printf
static int root_len = 0;
static char path[ PATH_MAX ];
static struct zip *z = NULL;
int pmkdir(const char *path);
void search_dir ( const char * name );
int unzip_file_pt(const char* unzip_file_in);
int zip_file_pt(const char * zip_file_in,const char * zip_file_out);
程序
/* unzip.c Copyright (c) 2015 zeerd.com.
*
* http://opensource.org/licenses/bsd-license.php
*
* Compile:
* ./configure --prefix=/usr
* make && sudo make isntall
* gcc unzip.c -lzip -o unzip
* 基本流程为:
(1)通过zip_open打开一个压缩文件,通过zip_get_num_entries获得压缩文件中条目数目(即:其中压缩文件的数目);
(2)遍历每个条目,通过zip_stat_index获得条目的基本信息;
(3)通过zip_fopen_index打开条目,通过zip_fread读取其中的数据,读出的数据为解压后的数据;
(4)创建本地文件,将解压后的数据流写入即可。
* Got libzip from http://www.nih.at/libzip
*/
#include "zip_pt.h"
int pmkdir(const char *path)
{
char name[ PATH_MAX ];
strcpy(name, path);
int i, len = strlen(name);
if (name[len-1]!='/') {
strcat(name, "/");
}
len = strlen(name);
for (i=1 ; i<len ; i++) {
if (name[i]=='/') {
name[i] = 0;
if ( access(name, NULL) !=0 ) {
if (mkdir(name, 0755) == -1) {
LOGE("mkdir error");
return -1;
}
}
name[i] = '/';
}
}
return 0;
}
int unzip_file_pt(const char* unzip_file_in)
{
int err = 0;
char strerr[1024];
struct zip *z = NULL;
z = zip_open(unzip_file_in, ZIP_CREATE, &err);
if (z != NULL) {
zip_int64_t i, c = zip_get_num_entries(z, ZIP_FL_UNCHANGED);
for (i=0; i<c ; i++) {
const char * name = zip_get_name(z, i, ZIP_FL_ENC_GUESS);
if (DBG_SEQ) LOGI("find %s\n", name);
char *d = strdup(name);
if (d != NULL) {
char *p = strrchr(d, '/');
if(p != NULL) {
*p = '\0';
pmkdir(d);
}else{
return -3;
}
free(d);
FILE *fp = fopen(name, "w+b");
struct zip_file *f = zip_fopen(z, name, 0);
if (f != NULL && fp != NULL) {
zip_int64_t j, n = 0;
char buf[8192] = "";
while ((n = zip_fread(f, buf, sizeof(buf))) > 0) {
for (j=0;j<n;j++) {
putc(buf[j], fp);
}
}
fclose(fp);
zip_fclose(f);
}
} else {
LOGE("memory low\n");
return -1;
}
}
err = zip_close(z);
} else {
zip_error_to_str(strerr, 1024, err, errno);
LOGE("operated zip fail for %s\n", strerr);
return -2;
}
return 1;
}
void search_dir ( const char * name )
{
struct stat _stbuf;
char pathBak[ PATH_MAX ];
strcpy(pathBak, path);
strncat( path, name, sizeof( path ));//path=name+/n
if (DBG_SEQ) LOGI( "searching %s\n", path );
if( stat( path, &_stbuf ) == 0 ) {
if( S_ISDIR( _stbuf.st_mode )) {
DIR * _dir;
struct dirent * _file;
_dir = opendir( path );
if( _dir ) {
if (DBG_SEQ) LOGD("find folder %s\n", path);
//Caution : no need to do this unless there is a empty folder
//zip_dir_add(z, name, ZIP_FL_ENC_GUESS);
strncat( path, "/", sizeof( path ));
while(( _file = readdir( _dir )) != NULL ) {
if( strncmp( _file->d_name, ".", 1 ) != 0 ) {
search_dir( _file->d_name);
}
}
closedir( _dir );
}
else {
LOGE( "open dir failed: %s\n", path );
}
}
else {
if (DBG_SEQ) LOGD("find file %s\n", path);
struct zip_source *s = zip_source_file(z, path, 0, -1);
if(s != NULL) {
if (DBG_SEQ) LOGE( "add dir file: %s\n", path);
// the file name give to zip_file_add() would include the path
//zip_file_add(z, &path[root_len+1], s,ZIP_FL_OVERWRITE|ZIP_FL_ENC_GUESS);
zip_file_add(z, &path[0], s,ZIP_FL_OVERWRITE|ZIP_FL_ENC_GUESS);
//would be used and freed by zip_close(),
//so don't free the zip_source here.
//zip_source_free(s);
} else {
LOGE( "zip_source_file failed for %s with the reason %s\n",
path, zip_strerror(z) );
}
}
}
else {
LOGE( "stat failed\n" );
}
/* remove parsed name */
strcpy(path, pathBak);
}
int zip_file_pt(const char * zip_file_in,const char * zip_file_out)
{
int err = 0;
char strerr[1024];
root_len = strlen(zip_file_in);
z = zip_open(zip_file_out, ZIP_CREATE|ZIP_EXCL, &err);
if (z != NULL) {
search_dir(zip_file_in);
err = zip_close(z);
}else{
return -2;
}
if (err != 0) {
zip_error_to_str(strerr, 1024, err, errno);
LOGE("operated zip fail for %s\n", strerr);
return -1;
}
return 1;
}
测试
#include <string.h>
#include "zip_pt.h"
using namespace std;
int main()
{
string nd_zip="/home/nvidia/robot";
string de_sec="/home/nvidia/robot1.zip";
cout << " 1.压缩 2.解压" << endl;
cout << ">> ";
cin >> x;
if (x == "1")
{
zip_file_pt(nd_zip.c_str(),de_sec.c_str());
}
else if (x == "2")
{
unzip_file_pt(de_sec.c_str());
}
else
{
cout << "请按照要求输入。。。。" << endl;
}
return 0;
}
ziplib.cmake
include_directories(${PROJECT_SOURCE_DIR}/ziplib/include)
link_directories(${PROJECT_SOURCE_DIR}/ziplib/lib)
cmake文件
cmake_minimum_required (VERSION 2.8)
project (zip)
set(CMAKE_CXX_STANDARD 17)
set(ALL_TARGET_LIBRARIES "")
include(cmake/ziplib.cmake)
add_executable(zip_main main/zip_other.cpp)
target_link_libraries(zip_main
pthread
-lzip
${ALL_TARGET_LIBRARIES}
)