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}
 )

Logo

更多推荐