利用zlib库进行zip解压
1:到zlib官网上下载zlib,本文下载的是1.2.8的版本。
2:进行./configure,然后make。
3:进入zlib库中的contrib/minizip/路径下make,生成的minizip是进行压缩,miniunz是进行解压zip文件。
下面讲解一下miniunz.c中的代码:
/*
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> #ifdef _WIN32
# include <direct.h>
# include <io.h>
#else
# include <unistd.h>
# include <utime.h>
#endif #include "unzip.h" #define CASESENSITIVITY (0)
#define WRITEBUFFERSIZE (8192)
#define MAXFILENAME (256) #ifdef _WIN32
#define USEWIN32IOAPI
#include "iowin32.h"
#endif
/*
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
*/ /* 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 */
void change_file_date(filename,dosdate,tmu_date)
const char *filename;
uLong dosdate;
tm_unz tmu_date;
{
#ifdef _WIN32
HANDLE hFile;
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; hFile = CreateFileA(filename,GENERIC_READ | GENERIC_WRITE,
,NULL,OPEN_EXISTING,,NULL);
GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
DosDateTimeToFileTime((WORD)(dosdate>>),(WORD)dosdate,&ftLocal);
LocalFileTimeToFileTime(&ftLocal,&ftm);
SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
CloseHandle(hFile);
#else
#ifdef unix || __APPLE__
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 > )
newdate.tm_year=tmu_date.tm_year - ;
else
newdate.tm_year=tmu_date.tm_year ;
newdate.tm_isdst=-; ut.actime=ut.modtime=mktime(&newdate);
utime(filename,&ut);
#endif
#endif
} /* mymkdir and change_file_date are not 100 % portable
As I don't know well Unix, I wait feedback for the unix portion */ int mymkdir(dirname)
const char* dirname;
{
int ret=;
#ifdef _WIN32
ret = _mkdir(dirname);
#elif unix
ret = mkdir (dirname,);
#elif __APPLE__
ret = mkdir (dirname,);
#endif
return ret;
} int makedir (newdir)
char *newdir;
{
char *buffer ;
char *p;
int len = (int)strlen(newdir); if (len <= )
return ; buffer = (char*)malloc(len+);
if (buffer==NULL)
{
printf("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
strcpy(buffer,newdir); if (buffer[len-] == '/') {
buffer[len-] = '\0';
}
if (mymkdir(buffer) == )
{
free(buffer);
return ;
} p = buffer+;
while ()
{
char hold; while(*p && *p != '\\' && *p != '/')
p++;
hold = *p;
*p = ;
if ((mymkdir(buffer) == -) && (errno == ENOENT))
{
printf("couldn't create directory %s\n",buffer);
free(buffer);
return ;
}
if (hold == )
break;
*p++ = hold;
}
free(buffer);
return ;
} void do_banner()
{
printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
} void do_help()
{
printf("Usage : miniunz [-e] [-x] [-v] [-l] [-o] [-p password] file.zip [file_to_extr.] [-d extractdir]\n\n" \
" -e Extract without pathname (junk paths)\n" \
" -x Extract with pathname\n" \
" -v list files\n" \
" -l list files\n" \
" -d directory to extract into\n" \
" -o overwrite files without prompting\n" \
" -p extract crypted file using password\n\n");
} void Display64BitsSize(ZPOS64_T n, int size_char)
{
/* to avoid compatibility problem , we do here the conversion */
char number[];
int offset=;
int pos_string = ;
number[]=;
for (;;) {
number[offset]=(char)((n%)+'');
if (number[offset] != '')
pos_string=offset;
n/=;
if (offset==)
break;
offset--;
}
{
int size_display_string = -pos_string;
while (size_char > size_display_string)
{
size_char--;
printf(" ");
}
} printf("%s",&number[pos_string]);
} int do_list(uf)
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=;i<gi.number_entry;i++)
{
char filename_inzip[];
unz_file_info64 file_info;
uLong ratio=;
const char *string_method;
char charCrypt=' ';
err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,,NULL,);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGetCurrentFileInfo\n",err);
break;
}
if (file_info.uncompressed_size>)
ratio = (uLong)((file_info.compressed_size*)/file_info.uncompressed_size); /* display a '*' if the file is crypted */
if ((file_info.flag & ) != )
charCrypt='*'; if (file_info.compression_method==)
string_method="Stored";
else
if (file_info.compression_method==Z_DEFLATED)
{
uInt iLevel=(uInt)((file_info.flag & 0x6)/);
if (iLevel==)
string_method="Defl:N";
else if (iLevel==)
string_method="Defl:X";
else if ((iLevel==) || (iLevel==))
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,);
printf(" %6s%c",string_method,charCrypt);
Display64BitsSize(file_info.compressed_size,);
printf(" %3lu%% %2.2lu-%2.2lu-%2.2lu %2.2lu:%2.2lu %8.8lx %s\n",
ratio,
(uLong)file_info.tmu_date.tm_mon + ,
(uLong)file_info.tmu_date.tm_mday,
(uLong)file_info.tmu_date.tm_year % ,
(uLong)file_info.tmu_date.tm_hour,(uLong)file_info.tmu_date.tm_min,
(uLong)file_info.crc,filename_inzip);
if ((i+)<gi.number_entry)
{
err = unzGoToNextFile(uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGoToNextFile\n",err);
break;
}
}
} return ;
} int do_extract_currentfile(uf,popt_extract_without_path,popt_overwrite,password)
unzFile uf;
const int* popt_extract_without_path;
int* popt_overwrite;
const char* password;
{
char filename_inzip[];
char* filename_withoutpath;
char* p;
int err=UNZ_OK;
FILE *fout=NULL;
void* buf;
uInt size_buf; unz_file_info64 file_info;
uLong ratio=;
err = unzGetCurrentFileInfo64(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,,NULL,); 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+;
p++;
} if ((*filename_withoutpath)=='\0')
{ // 文件夹
if ((*popt_extract_without_path)==)
{ // 创建文件夹
printf("creating directory: %s\n",filename_inzip);
mymkdir(filename_inzip);
}
}
else
{
const char* write_filename;
int skip=; if ((*popt_extract_without_path)==)
// 带有zip包中的文件路径
write_filename = filename_inzip;
else
// 不带有zip包中的文件路径
write_filename = filename_withoutpath; // 通过密码提取当前文件,如果没有密码则password为null
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
} // 提取当前文件成功,如果同名文件存在是否覆盖,popt_overwrite = 1表示无条件覆盖,popt_overwrite = 0表示不覆盖
if (((*popt_overwrite)==) && (err==UNZ_OK))
{
char rep=;
FILE* ftestexist;
// 以只读方式打开文件
ftestexist = FOPEN_FUNC(write_filename,"rb");
// 如果文件存在
if (ftestexist!=NULL)
{
fclose(ftestexist);
do
{
char answer[];
int ret; // 判断是否覆盖现有文件,Y是,N否,A以后都执行覆盖
printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ",write_filename);
ret = scanf("%1s",answer);
if (ret != )
{
exit(EXIT_FAILURE);
}
rep = answer[] ;
if ((rep>='a') && (rep<='z'))
rep -= 0x20;
}
while ((rep!='Y') && (rep!='N') && (rep!='A'));
} if (rep == 'N')
skip = ; if (rep == 'A')
*popt_overwrite=;
} // 要覆盖现有文件
if ((skip==) && (err==UNZ_OK))
{
fout=FOPEN_FUNC(write_filename,"wb");
/* some zipfile don't contain directory alone before file */
// 这里是一些zip包中的最上层的文件,这些文件不包含在任何文件夹中
if ((fout==NULL) && ((*popt_extract_without_path)==) &&
(filename_withoutpath!=(char*)filename_inzip))
{
char c=*(filename_withoutpath-);
*(filename_withoutpath-)='\0';
makedir(write_filename);
*(filename_withoutpath-)=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); // 循环读取当前文件,并写入硬盘
do
{
err = unzReadCurrentFile(uf,buf,size_buf);
if (err<)
{
printf("error %d with zipfile in unzReadCurrentFile\n",err);
break;
}
if (err>)
if (fwrite(buf,err,,fout)!=)
{
printf("error in writing extracted file\n");
err=UNZ_ERRNO;
break;
}
}
while (err>);
if (fout)
fclose(fout); // 修改文件的时间
if (err==)
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);
}
}
else
unzCloseCurrentFile(uf); /* don't lose the error */
} free(buf);
return err;
} int do_extract(uf,opt_extract_without_path,opt_overwrite,password)
unzFile uf;
int opt_extract_without_path;
int opt_overwrite;
const char* password;
{
uLong i;
unz_global_info64 gi;
int err;
FILE* fout=NULL; err = unzGetGlobalInfo64(uf,&gi);
if (err!=UNZ_OK)
printf("error %d with zipfile in unzGetGlobalInfo \n",err); for (i=;i<gi.number_entry;i++)
{
if (do_extract_currentfile(uf,&opt_extract_without_path,
&opt_overwrite,
password) != UNZ_OK)
break; if ((i+)<gi.number_entry)
{
err = unzGoToNextFile(uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGoToNextFile\n",err);
break;
}
}
} return ;
} int do_extract_onefile(uf,filename,opt_extract_without_path,opt_overwrite,password)
unzFile uf;
const char* filename;
int opt_extract_without_path;
int opt_overwrite;
const char* password;
{
int err = UNZ_OK;
if (unzLocateFile(uf,filename,CASESENSITIVITY)!=UNZ_OK)
{
printf("file %s not found in the zipfile\n",filename);
return ;
} if (do_extract_currentfile(uf,&opt_extract_without_path,
&opt_overwrite,
password) == UNZ_OK)
return ;
else
return ;
} int main(argc,argv)
int argc;
char *argv[];
{
const char *zipfilename=NULL; // zip包名
const char *filename_to_extract=NULL; // 指定文件名,然后在zip包中查找这个指定的文件
const char *password=NULL; // zip包的密码
char filename_try[MAXFILENAME+] = ""; // 当zip包名无效时,则会在zip包名后加上 .zip 标志存放在此变量中,然后深度操作此名
int i;
int ret_value=; // 返回值
int opt_do_list=; // 此标志表示是否只列出zip包中的文件列表,不解压zip包
int opt_do_extract=; // 此标志表示是否解压zip包
int opt_do_extract_withoutpath=; // 此标志表示解压zip包时,是否需要建立zip包中相应的目录路径
int opt_overwrite=; // 此标志表示解压zip包中的文件时,硬盘上已经存在此文件时,是否进行文件覆盖
int opt_extractdir=; // 此标志表示是否解压到指定的目录
const char *dirname=NULL;
unzFile uf=NULL; do_banner();
// 如果运行时提供的参数不对,将显示帮助
if (argc==)
{
do_help();
return ;
}
else
{
// 提取运行时输入的参数
for (i=;i<argc;i++)
{
if ((*argv[i])=='-')
{
const char *p=argv[i]+; while ((*p)!='\0')
{
char c=*(p++);
if ((c=='l') || (c=='L'))
opt_do_list = ;
if ((c=='v') || (c=='V'))
opt_do_list = ;
if ((c=='x') || (c=='X'))
opt_do_extract = ;
if ((c=='e') || (c=='E'))
opt_do_extract = opt_do_extract_withoutpath = ;
if ((c=='o') || (c=='O'))
opt_overwrite=;
if ((c=='d') || (c=='D'))
{
opt_extractdir=;
dirname=argv[i+];
} if (((c=='p') || (c=='P')) && (i+<argc))
{
password=argv[i+];
i++;
}
}
}
else
{
// 提取zip包名
if (zipfilename == NULL)
zipfilename = argv[i];
// 指定解压后的目录路径
else if ((filename_to_extract==NULL) && (!opt_extractdir))
filename_to_extract = argv[i] ;
}
}
} // 打开zip包
if (zipfilename!=NULL)
{ # ifdef USEWIN32IOAPI
zlib_filefunc64_def ffunc;
# endif strncpy(filename_try, zipfilename,MAXFILENAME-);
/* 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(zipfilename,&ffunc);
# else
uf = unzOpen64(zipfilename);
# 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",zipfilename,zipfilename);
return ;
}
printf("%s opened\n",filename_try); if (opt_do_list==)
ret_value = do_list(uf);
else if (opt_do_extract==)
{
// 改变当前的工作目录
#ifdef _WIN32
if (opt_extractdir && _chdir(dirname))
#else
if (opt_extractdir && chdir(dirname))
#endif
{
printf("Error changing into %s, aborting\n", dirname);
exit(-);
} 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;
}
利用zlib库进行zip解压的更多相关文章
- CentOS7下zip解压和unzip压缩文件
1.安装zip.unzip应用. yum install zip unzip
- MySQL For Windows Zip解压版安装
前言 Windows 下 MySQL 有msi和zip解压安装版两种,而zip版只需解压并做简单配置后就能使用,我个人比较喜欢这种方式. 注意我们这里说的MySQL是指MySQL服务器,有很多初学的同 ...
- 解决ubuntu中zip解压的中文乱码问题
转自解决ubuntu中zip解压的中文乱码问题 在我的ubuntu12.10中,发现显示中文基本都是正常的,只有在解压windows传过来的zip文件时,才会出现乱码.所以,我用另一个方法解决中文乱码 ...
- JAVA zip解压 MALFORMED 错误
最近在在使用zip 解压时,使用JDK1.7及以上版本在解压时,某些文件会报异常 Exception in thread "main" java.lang.IllegalArgum ...
- windows下tomcat zip解压版安装方法
下面记录一下在win7(32位)系统下,安装zip解压版的方法: 一.下载zip压缩包 地址:http://tomcat.apache.org/download-80.cgi 二.解压 我把解压包解压 ...
- 【转载】在linux下别用zip 用tar来压缩文件 zip解压后还是utf-8 window10是GBK
3.2 使用 unzip 命令解压缩 zip 文件 将 shiyanlou.zip 解压到当前目录: $ unzip shiyanlou.zip 使用安静模式,将文件解压到指定目录: $ un ...
- Java zip解压,并遍历zip中的配置文件 .cfg或.properties
1.解析cfg或properties配置文件 讲配置文件,读取,并封装成为map类型数据 /** * 解析cfg文件 * * @param cfgFile * @return */ public st ...
- ubuntu zip解压
您好,zip xx.zip压缩,unzip xx.zip 解压,tar zcvf xx.tar.gz压缩tar zxvf xx.tar.gz解压
- zip 解压脚本
zip 解压脚本 gpk-unzip.py #!/usr/bin/env python # -*- coding: utf-8 -*- # unzip-gbk.py import os import ...
随机推荐
- D3.js部署node环境开发
总结一段D3.js部署node环境的安装过程 准备阶段: 首先电脑上要安装node环境,这个阶段过滤掉,如果node环境都不会装,那就别玩基于node环境搞的其他东西了. 搭建环境: 我在自己的F:系 ...
- Prototypes in Javascript 收集.__proto__
It’s important to understand that a function’s prototype property has nothing to do with it’s actual ...
- 【Alpha】Daily Scrum Meeting第六次
一.本次Daily Scrum Meeting主要内容 各队员的任务完成情况 接下去要做的任务有哪些方面的问题 二.项目进展 学号尾数 今日已完成任务 接下去要做 502 统一Excel表头数据的英文 ...
- 堆排序 Heapsort
Prime + Heap 简直神了 时间优化好多,顺便就把Heapsort给撸了一发 具体看图 Heapsort利用完全二叉树+大(小)顶锥的结构每次将锥定元素和锥最末尾的元素交换 同时大(小)顶锥元 ...
- HDU1426 DFS
Sudoku Killer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tot ...
- 【转】最近公共祖先(LCA)
基本概念 LCA:树上的最近公共祖先,对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. RMQ:区间最小值查询问题.对于长度为n的 ...
- KVM 基本命令
一.问题描述: KVM中宿主机通过console无法连接客户机,卡在这里不动了. # virsh console vm01 Connected to domain vm01 Escape charac ...
- ionic 踩过的坑-基本布局
目录: 标题栏 : ion-header-bar 页脚栏 : ion-footer-bar header/footer : 样式及内容 内容区 : ion-content 滚动框 : ion-scro ...
- 10个jQuery小技巧
收集的10个 jQuery 小技巧/代码片段,可以帮你快速开发. 1.返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. $('a.top' ...
- 后台进程管理supervisor
一.安装 该工具是python的一个软件包,需要安装python及其python-setuptools 二.安装完后会在python的bin目录下找到对应的命令文件 三.安装supervisor为服务 ...