基于zlib实现的zip文件解压缩,支持目录解压缩,使用c语言实现

2023-11-11

目前用到了解压缩目录的功能,使用zlib来实现,但是找遍了网上的例子很少涉及到使用c语言编写并且完成多目录解压缩的例子,于是自己查看源码的minizip例子,修改了一下供大家参考。

zlib官网下载:https://www.zlib.net/
当前我是使用的最新版本为“zlib-1.2.11”

minizip例子目录:zlib-1.2.11/contrib/minizip

以下是做出修改的代码提供参考,如需完整的代码资源请到下面网址下载
https://download.csdn.net/download/LK_whq/15118857
代码资源中没有提供Makefile需要使用者根据需要自行编写,也可以就我修改的代码把main.c和minizip.c合并后在zlib/contrib/minizip目录下修改Makefile来实现。本文中的修改是为了做成单独的解压缩库而进行的。如有不方便之处敬请谅解。

改动:解压文件miniunz.c
将miniunz.c的main函数修改为一个接口,提供他人使用,如下:

/*
   miniunz.c
   Version 1.1, February 14h, 2010
   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )

         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )

         Modifications of Unzip for Zip64
         Copyright (C) 2007-2008 Even Rouault

         Modifications for Zip64 support on both zip and unzip
         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
*/

#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
        #ifndef __USE_FILE_OFFSET64
                #define __USE_FILE_OFFSET64
        #endif
        #ifndef __USE_LARGEFILE64
                #define __USE_LARGEFILE64
        #endif
        #ifndef _LARGEFILE64_SOURCE
                #define _LARGEFILE64_SOURCE
        #endif
        #ifndef _FILE_OFFSET_BIT
                #define _FILE_OFFSET_BIT 64
        #endif
#endif

#ifdef __APPLE__
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <utime.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "miniunz.h"
#include "unzip.h"

#define CASESENSITIVITY (0)
#define WRITEBUFFERSIZE (8192)
#define MAXFILENAME (256)

/*
  mini unzip, demo of unzip package

  usage :
  Usage : miniunz [-exvlo] file.zip [file_to_extract] [-d extractdir]

  list the file in the zipfile, and print the content of FILE_ID.ZIP or README.TXT
    if it exists
*/


static myminiunz_t g_myminiunz;
void *get_myminiunz_handle(void)
{
    return &g_myminiunz;
}

/* change_file_date : change the date/time of a file
    filename : the filename of the file where date/time must be modified
    dosdate : the new date at the MSDos format (4 bytes)
    tmu_date : the SAME new date at the tm_unz format */
static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date)
{
    struct utimbuf ut;
    struct tm newdate;
    newdate.tm_sec = tmu_date.tm_sec;
    newdate.tm_min = tmu_date.tm_min;
    newdate.tm_hour = tmu_date.tm_hour;
    newdate.tm_mday = tmu_date.tm_mday;
    newdate.tm_mon = tmu_date.tm_mon;
    if (tmu_date.tm_year > 1900)
        newdate.tm_year = tmu_date.tm_year - 1900;
    else
        newdate.tm_year = tmu_date.tm_year;
    newdate.tm_isdst = -1;

    ut.actime = ut.modtime = mktime(&newdate);
    utime(filename, &ut);
}

/* mymkdir and change_file_date are not 100 % portable
   As I don't know well Unix, I wait feedback for the unix portion */

static int mymkdir(const char *dirname)
{
    int ret = 0;
    ret = mkdir(dirname, 0775);
    return ret;
}

static int makedir(const char *newdir)
{
    char *buffer;
    char *p;
    int len = (int)strlen(newdir);

    if (len <= 0)
        return 0;

    buffer = (char *)malloc(len + 1);
    if (buffer == NULL) {
        printf("Error allocating memory\n");
        return UNZ_INTERNALERROR;
    }
    strcpy(buffer, newdir);

    if (buffer[len - 1] == '/') {
        buffer[len - 1] = '\0';
    }
    if (mymkdir(buffer) == 0) {
        free(buffer);
        return 1;
    }

    p = buffer + 1;
    while (1) {
        char hold;

        while (*p && *p != '\\' && *p != '/')
            p++;
        hold = *p;
        *p = 0;
        if ((mymkdir(buffer) == -1) && (errno == ENOENT)) {
            printf("couldn't create directory %s\n", buffer);
            free(buffer);
            return 0;
        }
        if (hold == 0)
            break;
        *p++ = hold;
    }
    free(buffer);
    return 1;
}

static void Display64BitsSize(ZPOS64_T n, int size_char)
{
    /* to avoid compatibility problem , we do here the conversion */
    char number[21];
    int offset = 19;
    int pos_string = 19;
    number[20] = 0;
    for (;;) {
        number[offset] = (char)((n % 10) + '0');
        if (number[offset] != '0')
            pos_string = offset;
        n /= 10;
        if (offset == 0)
            break;
        offset--;
    }
    {
        int size_display_string = 19 - pos_string;
        while (size_char > size_display_string) {
            size_char--;
            printf(" ");
        }
    }

    printf("%s", &number[pos_string]);
}

static int do_list(unzFile uf)
{
    uLong i;
    unz_global_info64 gi;
    int err;

    err = unzGetGlobalInfo64(uf, &gi);
    if (err != UNZ_OK)
        printf("error %d with zipfile in unzGetGlobalInfo \n", err);
    printf("  Length  Method     Size Ratio   Date    Time   CRC-32     Name\n");
    printf("  ------  ------     ---- -----   ----    ----   ------     ----\n");
    for (i = 0; i < gi.number_entry; i++) {
        char filename_inzip[256];
        unz_file_info64 file_info;
        uLong ratio = 0;
        const char *string_method;
        char charCrypt = ' ';
        err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
        if (err != UNZ_OK) {
            printf("error %d with zipfile in unzGetCurrentFileInfo\n", err);
            break;
        }
        if (file_info.uncompressed_size > 0)
            ratio = (uLong)((file_info.compressed_size * 100) / file_info.uncompressed_size);

        /* display a '*' if the file is crypted */
        if ((file_info.flag & 1) != 0)
            charCrypt = '*';

        if (file_info.compression_method == 0)
            string_method = "Stored";
        else if (file_info.compression_method == Z_DEFLATED) {
            uInt iLevel = (uInt)((file_info.flag & 0x6) / 2);
            if (iLevel == 0)
                string_method = "Defl:N";
            else if (iLevel == 1)
                string_method = "Defl:X";
            else if ((iLevel == 2) || (iLevel == 3))
                string_method = "Defl:F"; /* 2:fast , 3 : extra fast*/
        }
        else if (file_info.compression_method == Z_BZIP2ED) {
            string_method = "BZip2 ";
        }
        else
            string_method = "Unkn. ";

        Display64BitsSize(file_info.uncompressed_size, 7);
        printf("  %6s%c", string_method, charCrypt);
        Display64BitsSize(file_info.compressed_size, 7);
        printf(" %3lu%%  %2.2lu-%2.2lu-%2.2lu  %2.2lu:%2.2lu  %8.8lx   %s\n",
               ratio,
               (uLong)file_info.tmu_date.tm_mon + 1,
               (uLong)file_info.tmu_date.tm_mday,
               (uLong)file_info.tmu_date.tm_year % 100,
               (uLong)file_info.tmu_date.tm_hour, (uLong)file_info.tmu_date.tm_min,
               (uLong)file_info.crc, filename_inzip);
        if ((i + 1) < gi.number_entry) {
            err = unzGoToNextFile(uf);
            if (err != UNZ_OK) {
                printf("error %d with zipfile in unzGoToNextFile\n", err);
                break;
            }
        }
    }

    return 0;
}

static int do_extract_currentfile(unzFile uf, const int *popt_extract_without_path, int *popt_overwrite, const char *password)
{
    char filename_inzip[256];
    char *filename_withoutpath;
    char *p;
    int err = UNZ_OK;
    FILE *fout = NULL;
    void *buf;
    uInt size_buf;

    unz_file_info64 file_info;
    err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);

    if (err != UNZ_OK) {
        printf("error %d with zipfile in unzGetCurrentFileInfo\n", err);
        return err;
    }

    size_buf = WRITEBUFFERSIZE;
    buf = (void *)malloc(size_buf);
    if (buf == NULL) {
        printf("Error allocating memory\n");
        return UNZ_INTERNALERROR;
    }

    p = filename_withoutpath = filename_inzip;
    while ((*p) != '\0') {
        if (((*p) == '/') || ((*p) == '\\'))
            filename_withoutpath = p + 1;
        p++;
    }

    if ((*filename_withoutpath) == '\0') {
        if ((*popt_extract_without_path) == 0) {
            // printf("creating directory: %s\n", filename_inzip);
            mymkdir(filename_inzip);
            g_myminiunz.curr_entry++;
        }
    }
    else {
        const char *write_filename;
        int skip = 0;

        if ((*popt_extract_without_path) == 0)
            write_filename = filename_inzip;
        else
            write_filename = filename_withoutpath;

        err = unzOpenCurrentFilePassword(uf, password);
        if (err != UNZ_OK) {
            printf("error %d with zipfile in unzOpenCurrentFilePassword\n", err);
        }

        if (((*popt_overwrite) == 0) && (err == UNZ_OK)) {
            char rep = 0;
            FILE *ftestexist;
            ftestexist = FOPEN_FUNC(write_filename, "rb");
            if (ftestexist != NULL) {
                fclose(ftestexist);
                do {
                    char answer[128];
                    int ret;

                    printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ", write_filename);
                    ret = scanf("%1s", answer);
                    if (ret != 1) {
                        exit(EXIT_FAILURE);
                    }
                    rep = answer[0];
                    if ((rep >= 'a') && (rep <= 'z'))
                        rep -= 0x20;
                } while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
            }

            if (rep == 'N')
                skip = 1;

            if (rep == 'A')
                *popt_overwrite = 1;
        }

        if ((skip == 0) && (err == UNZ_OK)) {
            fout = FOPEN_FUNC(write_filename, "wb");
            /* some zipfile don't contain directory alone before file */
            if ((fout == NULL) && ((*popt_extract_without_path) == 0) &&
                (filename_withoutpath != (char *)filename_inzip))
            {
                char c = *(filename_withoutpath - 1);
                *(filename_withoutpath - 1) = '\0';
                makedir(write_filename);
                *(filename_withoutpath - 1) = c;
                fout = FOPEN_FUNC(write_filename, "wb");
            }

            if (fout == NULL) {
                printf("error opening %s\n", write_filename);
            }
        }

        if (fout != NULL) {
            // printf(" extracting: %s\n", write_filename);
            sprintf(g_myminiunz.extract_tips, "extracting: %s", write_filename);

            do {
                err = unzReadCurrentFile(uf, buf, size_buf);
                if (err < 0) {
                    printf("error %d with zipfile in unzReadCurrentFile\n", err);
                    break;
                }
                if (err > 0)
                    if (fwrite(buf, err, 1, fout) != 1) {
                        printf("error in writing extracted file\n");
                        err = UNZ_ERRNO;
                        break;
                    }
            } while (err > 0);
            if (fout)
                fclose(fout);

            if (err == 0)
                change_file_date(write_filename, file_info.dosDate,
                                 file_info.tmu_date);
        }
        if (err == UNZ_OK) {
            err = unzCloseCurrentFile(uf);
            if (err != UNZ_OK) {
                printf("error %d with zipfile in unzCloseCurrentFile\n", err);
            }
            g_myminiunz.curr_entry++;
        }
        else
            unzCloseCurrentFile(uf); /* don't lose the error */
    }

    free(buf);
    return err;
}

static int do_extract(unzFile uf, int opt_extract_without_path, int opt_overwrite, const char *password)
{
    uLong i;
    unz_global_info64 gi;
    int err;

    err = unzGetGlobalInfo64(uf, &gi);
    if (err != UNZ_OK) {
        printf("error %d with zipfile in unzGetGlobalInfo \n", err);
        return err;
    }

    g_myminiunz.number_entry = gi.number_entry;

    for (i = 0; i < gi.number_entry; i++) {
        if (do_extract_currentfile(uf, &opt_extract_without_path, &opt_overwrite, password) != UNZ_OK) {
            err = UNZ_BADZIPFILE;
            g_myminiunz.curr_entry = g_myminiunz.number_entry;

            break;
        }

        if ((i + 1) < gi.number_entry) {
            err = unzGoToNextFile(uf);
            if (err != UNZ_OK) {
                printf("error %d with zipfile in unzGoToNextFile\n", err);
                break;
            }
        }
    }

    return err;
}

static int do_extract_onefile(unzFile uf, const char *filename, int opt_extract_without_path, int opt_overwrite, const char *password)
{
    if (unzLocateFile(uf, filename, CASESENSITIVITY) != UNZ_OK) {
        printf("file %s not found in the zipfile\n", filename);
        return 2;
    }

    if (do_extract_currentfile(uf, &opt_extract_without_path,
                               &opt_overwrite,
                               password) == UNZ_OK)
        return 0;
    else
        return 1;
}

// 当opt_extractdir = 1时,dirname不能为NULL
int start_extract_zip(const char *zipfilename, const char *password, int opt_extractdir, const char *dirname)
{
    char filename_try[MAXFILENAME + 16] = "";
    const char *filename_to_extract = NULL;
    int ret_value = -1;
    int opt_do_list = 0;
    int opt_do_extract = 1;
    int opt_do_extract_withoutpath = 0;
    int opt_overwrite = 1;
    unzFile uf = NULL;

    g_myminiunz.number_entry = 0;
    g_myminiunz.curr_entry = 0;
    
    if (zipfilename != NULL) {
        strncpy(filename_try, zipfilename, MAXFILENAME - 1);
        /* strncpy doesnt append the trailing NULL, of the string is too long. */
        filename_try[MAXFILENAME] = '\0';
        uf = unzOpen64(zipfilename);
        if (uf == NULL) {
            strcat(filename_try, ".zip");
            uf = unzOpen64(filename_try);
        }
    }

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

    if (opt_do_list == 1)
        ret_value = do_list(uf);
    else if (opt_do_extract == 1) {
        if (opt_extractdir && chdir(dirname)) {
            printf("Error changing into %s, aborting\n", dirname);
            exit(-1);
        }

        if (opt_extractdir == 0) {
            filename_to_extract = zipfilename;
        }

        if (filename_to_extract == NULL)
            ret_value = do_extract(uf, opt_do_extract_withoutpath, opt_overwrite, password);
        else
            ret_value = do_extract_onefile(uf, filename_to_extract, opt_do_extract_withoutpath, opt_overwrite, password);
    }

    unzClose(uf);
    return ret_value;
}

改动2:minizip.c,由于minizip.c中并没有给出压缩文件目录的例子,经研究做出如下修改

/*
   minizip.c
   Version 1.1, February 14h, 2010
   sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )

         Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )

         Modifications of Unzip for Zip64
         Copyright (C) 2007-2008 Even Rouault

         Modifications for Zip64 support on both zip and unzip
         Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
*/

#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
        #ifndef __USE_FILE_OFFSET64
                #define __USE_FILE_OFFSET64
        #endif
        #ifndef __USE_LARGEFILE64
                #define __USE_LARGEFILE64
        #endif
        #ifndef _LARGEFILE64_SOURCE
                #define _LARGEFILE64_SOURCE
        #endif
        #ifndef _FILE_OFFSET_BIT
                #define _FILE_OFFSET_BIT 64
        #endif
#endif

#ifdef __APPLE__
// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
#define FTELLO_FUNC(stream) ftello(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
#else
#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
#define FTELLO_FUNC(stream) ftello64(stream)
#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <utime.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "zip.h"


#define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256)

static uLong filetime(f, tmzip, dt)
    char *f;               /* name of file to get info on */
    tm_zip *tmzip;         /* return value: access, modific. and creation times */
    uLong *dt;             /* dostime */
{
  int ret=0;
  struct stat s;        /* results of stat() */
  struct tm* filedate;
  time_t tm_t=0;

  if (strcmp(f,"-")!=0)
  {
    char name[MAXFILENAME+1];
    int len = strlen(f);
    if (len > MAXFILENAME)
      len = MAXFILENAME;

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

    if (name[len - 1] == '/')
      name[len - 1] = '\0';
    /* not all systems allow stat'ing a file with / appended */
    if (stat(name,&s)==0)
    {
      tm_t = s.st_mtime;
      ret = 1;
    }
  }
  filedate = localtime(&tm_t);

  tmzip->tm_sec  = filedate->tm_sec;
  tmzip->tm_min  = filedate->tm_min;
  tmzip->tm_hour = filedate->tm_hour;
  tmzip->tm_mday = filedate->tm_mday;
  tmzip->tm_mon  = filedate->tm_mon ;
  tmzip->tm_year = filedate->tm_year;

  return ret;
}

#if 0
static int check_exist_file(filename)
    const char* filename;
{
    FILE* ftestexist;
    int ret = 1;
    ftestexist = FOPEN_FUNC(filename,"rb");
    if (ftestexist==NULL)
        ret = 0;
    else
        fclose(ftestexist);
    return ret;
}
#endif

/* calculate the CRC32 of a file,
   because to encrypt a file, we need known the CRC32 of the file before */
static int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
{
   unsigned long calculate_crc=0;
   int err=ZIP_OK;
   FILE * fin = FOPEN_FUNC(filenameinzip,"rb");

   unsigned long size_read = 0;
   unsigned long total_read = 0;
   if (fin==NULL)
   {
       err = ZIP_ERRNO;
   }

    if (err == ZIP_OK)
        do
        {
            err = ZIP_OK;
            size_read = (int)fread(buf,1,size_buf,fin);
            if (size_read < size_buf)
                if (feof(fin)==0)
            {
                printf("error in reading %s\n",filenameinzip);
                err = ZIP_ERRNO;
            }

            if (size_read>0)
                calculate_crc = crc32(calculate_crc,buf,size_read);
            total_read += size_read;

        } while ((err == ZIP_OK) && (size_read>0));

    if (fin)
        fclose(fin);

    *result_crc=calculate_crc;
    // printf("file %s crc %lx\n", filenameinzip, calculate_crc);
    return err;
}

static int isLargeFile(const char* filename)
{
  int largeFile = 0;
  ZPOS64_T pos = 0;
  FILE* pFile = FOPEN_FUNC(filename, "rb");

  if(pFile != NULL)
  {
    FSEEKO_FUNC(pFile, 0, SEEK_END);
    pos = FTELLO_FUNC(pFile);

                // printf("File : %s is %lld bytes\n", filename, pos);

    if(pos >= 0xffffffff)
     largeFile = 1;

                fclose(pFile);
  }

 return largeFile;
}


typedef struct _myminiz_status {
    void *buf;
    int size_buf;
    zipFile zf;
} myminiz_t;

static myminiz_t g_myminiz;
void *create_zip_file(char *filename_try, int opt_overwrite)
{
   int dot_found = 0;
   int len=(int)strlen(filename_try);

    g_myminiz.size_buf = WRITEBUFFERSIZE;
    g_myminiz.buf = (void*)malloc(g_myminiz.size_buf);
    if (g_myminiz.buf == NULL) {
        printf("Error allocating memory\n");
        return NULL;
    }

   for (int i = 0; i < len; i++)
       if (filename_try[i] == '.')
           dot_found = 1;

   if (dot_found == 0)
       strcat(filename_try, ".zip");


   g_myminiz.zf = zipOpen64(filename_try, (opt_overwrite == 2) ? 2 : 0);
   if (g_myminiz.zf == NULL) {
       free(g_myminiz.buf);
       g_myminiz.buf = NULL;
       printf("error opening %s\n", filename_try);
   }
   else
       printf("creating %s\n", filename_try);

   return (void *)g_myminiz.zf;
}

int write_file_to_zipfile(char *filename, char *password)
{
    FILE *fin;
    int err = 0;
    int size_read;
    int opt_compress_level = Z_DEFAULT_COMPRESSION;
    const char *filenameinzip = filename;
    const char *savefilenameinzip;
    zip_fileinfo zi;
    unsigned long crcFile = 0;
    int zip64 = 0;

    zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
        zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
    zi.dosDate = 0;
    zi.internal_fa = 0;
    zi.external_fa = 0;
    filetime(filenameinzip, &zi.tmz_date, &zi.dosDate);

    if ((password != NULL) && (err == ZIP_OK))
        err = getFileCrc(filenameinzip, g_myminiz.buf, g_myminiz.size_buf, &crcFile);

    zip64 = isLargeFile(filenameinzip);

    /* The path name saved, should not include a leading slash. */
    /*if it did, windows/xp and dynazip couldn't read the zip file. */
    savefilenameinzip = filenameinzip;
    while (savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/')
    {
        savefilenameinzip++;
    }

    /**/
    err = zipOpenNewFileInZip3_64(g_myminiz.zf, savefilenameinzip, &zi,
                                  NULL, 0, NULL, 0, NULL /* comment*/,
                                  (opt_compress_level != 0) ? Z_DEFLATED : 0,
                                  opt_compress_level, 0,
                                  /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
                                  -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                  password, crcFile, zip64);

    if (err != ZIP_OK)
        printf("error in opening %s in zipfile\n", filenameinzip);
    else
    {
        fin = FOPEN_FUNC(filenameinzip, "rb");
        if (fin == NULL)
        {
            err = ZIP_ERRNO;
            printf("error in opening %s for reading\n", filenameinzip);
        }
    }

    if (err == ZIP_OK)
        do
        {
            err = ZIP_OK;
            size_read = (int)fread(g_myminiz.buf, 1, g_myminiz.size_buf, fin);
            if (size_read < g_myminiz.size_buf)
                if (feof(fin) == 0)
                {
                    printf("error in reading %s\n", filenameinzip);
                    err = ZIP_ERRNO;
                }

            if (size_read > 0)
            {
                err = zipWriteInFileInZip(g_myminiz.zf, g_myminiz.buf, size_read);
                if (err < 0)
                {
                    printf("error in writing %s in the zipfile\n",
                           filenameinzip);
                }
            }
        } while ((err == ZIP_OK) && (size_read > 0));

    if (fin)
        fclose(fin);

    if (err < 0)
        err = ZIP_ERRNO;
    else
    {
        err = zipCloseFileInZip(g_myminiz.zf);
        if (err != ZIP_OK)
            printf("error in closing %s in the zipfile\n", filenameinzip);
    }

    return err;
}

int close_zip_file(void)
{
    int errclose = zipClose(g_myminiz.zf, NULL);
    if (errclose != ZIP_OK)
        printf("error in closing .zip file\n");
    else {
        free(g_myminiz.buf);
        g_myminiz.buf = NULL;
    }

    return errclose;
}

这两个函数全部都是以接口的形式提供给上层应用使用,下面是给出的一个小程序main.c,提供参考:

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <miniunz.h>
#include <minizip.h>

static void foreach_dir_all_files(char *fpath)
{
  char filepath[128];
  DIR *dir = open_dir(fpath);
  struct dirent *dirp;

  if (NULL != dir) {

    while ((dirp = read_dir(dir)) != NULL) {
      if (dirp->d_type == DT_REG) {
        sprintf(filepath, "%s/%s", fpath, dirp->d_name);
        char *p = &filepath[10];
        write_file_to_zipfile(p, NULL); //第二个参数是密码,没有就写NULL
        printf("compress: %s", filepath);
      } 
      else if (dirp->d_type == DT_DIR) {
        if (strcmp(dirp->d_name, ".") || strcmp(dirp->d_name, "..")) continue;
        sprintf(filepath, "%s/%s", fpath, dirp->d_name);
        foreach_dir_all_files(filepath);
      }
    }
    closedir(dir);
  }  
}

int main(int argc, char *argv[])
{
  //解压,支持目录解压
  start_extract_zip("./test.zip", NULL, 1, "./");
  
  //压缩,要复杂一些,支持目录压缩
  if (NULL == create_zip_file("./test2.zip", 0)) {
    return 0;
  }
  else {
    foreach_dir_all_files("/opt/soft");
  }

  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于zlib实现的zip文件解压缩,支持目录解压缩,使用c语言实现 的相关文章

随机推荐

  • 关系代数之连接 (Join)和除(Division)

    关系代数之连接 Join 和除 Division 数据库技术中这两个概念 对初学者而言 理解比较困难 本文对此进行深入浅出的解释 连接 Join 联接 定义 从两个关系的笛卡尔积中选取属性间满足一定条件的元组 记作 其中A和B分别为R和S上
  • Illumina输出文件详解

    Illumina输出文件详解 Illumina测序原理 next seq 550 基本过程 基本概念 BCL文件 Base Call Files BCI文件 Base Call Index Files BGZF文件 Block GNU ZI
  • C++泛型函数及模版类

    什么是泛型编程 简单来说 泛型编程 意思就是针对广泛类型的编程方式 具体类型可以有不同的实现方式 但是针对广泛类型编程 就能在需要调用时才指定参数类型或者调用类型 泛型编程是一种基于发现高效算法的最抽象表示的编程方法 也就是说 以算法为起点
  • youtube-dl下载速度慢解决方法

    Python版本 3 10 运行环境 Windows10 问题描述 在使用youtube dl下载视频时网速很慢 并一直限制在某个速度上 如下 解决办法 进入windows 安全中心 病毒和威胁防护 管理设置 点击添加或删除排除项 添加排除
  • mysql 基于gtid ssl 主从复制(半同步)

    主库 1 生成证书 根据实际的mysql安装路径 data db mysql 5 7 26 bin mysql ssl rsa setup d data conf mysqldb 2 修改权限 cd data conf mysqldb ch
  • ch05与游戏世界交互——鼠标打飞碟小游戏

    游戏内容要求 游戏有 n 个 round 每个 round 都包括10 次 trial 每个 trial 的飞碟的色彩 大小 发射位置 速度 角度 同时出现的个数都可能不同 它们由该 round 的 ruler 控制 每个 trial 的飞
  • chroot命令

    转载 理解 chroot 什么是 chroot chroot 即 change root directory 更改 root 目录 在 linux 系统中 系统默认的目录结构都是以 即是以根 root 开始的 而在使用 chroot 之后
  • 感知机对偶算法

    知识源于 统计学习方法 第二版 李航 感知机 perception 一种二分类的线性分类模型 输入为实例的特征向量 输出为实例的类别 二分类类别为 1 1二值 用算法2 2 感知机学习算法的对偶形式 代码实现例2 2 一 实验目的 用算法2
  • 1061 判断题

    判断题的评判很简单 本题就要求你写个简单的程序帮助老师判题并统计学生们判断题的得分 输入格式 输入在第一行给出两个不超过 100 的正整数 N 和 M 分别是学生人数和判断题数量 第二行给出 M 个不超过 5 的正整数 是每道题的满分值 第
  • POJ-3253 Fence Repair

    农夫约翰想修理牧场周围的一小段围栏 他测量围栏并认定他需要 1 20000 厚木板 每一个都具有一些整数长度大号我 1 大号我 50000 单元 然后 他购买一块长板足够长 以便看到N块板 即 其长度是长度L i的总和 FJ忽略了 切口 锯
  • VPP代码阅读中文注解--dlist.h

    双向链表算法 本双向链表的所有元素存储在一个pool中 根据pool中内存块的序号进行索引 typedef struct u32 next u32 prev u32 value dlist elt t 本双向链表中每一个元素的结构 valu
  • Linux基础命令使用(4)

    which命令 which 命令的作用是 在 PATH 变量指定的路径中搜索可执行文件的所在位置 它一般用来确认系统中是否安装了指定的软件 which 可执行文件名称 确认是否安装了 gcc which gcc whereis命令 wher
  • 移动基站

    中国移动的基站采用小区制 覆盖范围几KM 而联通采用大区制 可以覆盖几十KM 辐射的频率大小和能量决定覆盖范围 也从另一角度来看 由能量守恒的角度来分析 手机辐射大的其基站辐射小 GSM 反之手机辐射小的其基站辐射大 CDMA 一般分为以下
  • Liferay中的Portlet事件通信

    Liferay中的Portlet事件通信在有的项目开发中是需要实现的一种机制 下面转自http liferaycms blogspot com 2011 07 inter portlet communication html Inter p
  • Java 5-2、用户模块-7个接口实现

    5 2 用户模块 7个接口实现 web端注册 app端注册 所需参数更少 登录 用户详情 修改密码 用户开关 修改用户信息 一 新增类 AppUserService java 此类需定义和mapper层接口大致相同的方法 仅做返回值取舍 因
  • 编译报错:Module parse failed: Unexpected token (18:41)

    error in node modules yargs lib platform shims esm mjs Module parse failed Unexpected token 18 41 You may need an approp
  • 科研笔记(九)重构智能手机CSI指纹用于室内定位(上)

    重构智能手机CSI指纹用于室内定位 题目 CRISLoc Reconstructable CSI Fingerprinting for Indoor Smartphone Localization 论文作者 Zhihui Gao Yunfa
  • Google Chrome访问出现 NET::ERR_CERT_INVALID

    前言 搭建一个nginx网站后 访问出现 您的连接不是私密连接 解决Google Chrome浏览器访问一个网页出现 NET ERR CERT INVALID 这是因为访问没有使用信任的CA证书的网站 chrome提示NET ERR CER
  • 电脑开机就重启循环_如何远程重启服务器???

    重启远程服务器重启的方法如下 方法一 使用windows自带的shutdown命令 远程重启服务器 当远程桌面连接服务无法顺利使用后 首先要确定的是服务器是否真的死机 通过ping目标服务器IP看是否畅通或者访问该服务器上的相关网络服务看是
  • 基于zlib实现的zip文件解压缩,支持目录解压缩,使用c语言实现

    目前用到了解压缩目录的功能 使用zlib来实现 但是找遍了网上的例子很少涉及到使用c语言编写并且完成多目录解压缩的例子 于是自己查看源码的minizip例子 修改了一下供大家参考 zlib官网下载 https www zlib net 当前