[zlib]_[0基础]_[使用Zlib完整解压zip内容]
场景:
1. 解压文件一般用在下载了一个zip文件之后解压,或者分析某个文件须要解压的操作上.
2. 解压文件,特别是解压带目录的zip文件往往系统没有提供这类Win32 API,当然C#自带库能解压, 当然这里仅仅讨论C/C++, 像C#和Java这样的开挂的标准库不在考虑范围内.
3. zlib解压文件的使用样例在 contrib\minizip 样例里. 这里基本是直接提取miniunz.c 的代码进行封装解压就可以, 仅仅是改了下支持中文路径.
主文件 zip_util.cpp
#include "stdafx.h" #include "zip_util.h"
#include "unzip.h" #include <iostream>
#include <string>
#include <algorithm>
#include <stdlib.h> #include <zlib.h>
#include "ioapi.h"
#include "iowin32.h"
#include "wrap_object.h" using namespace std; #define CASESENSITIVITY (0)
#define WRITEBUFFERSIZE (8192)
#define MAXFILENAME (256) unzFile ZipUtil::UnzOpen64(const wchar_t* path)
{
zlib_filefunc64_def ffunc;
fill_win32_filefunc64W(&ffunc);
unzFile zf = unzOpen2_64(path,&ffunc);
return zf;
} char* ConvertUnicodeToUtf8(const wchar_t* unicode)
{
if(unicode == NULL)
{
return strdup("\0");
} int len;
len = WideCharToMultiByte(CP_UTF8, 0,unicode, -1, NULL, 0, NULL, NULL);
char *szUtf8 = (char*)malloc(len + 1);
memset(szUtf8, 0, len + 1);
WideCharToMultiByte(CP_UTF8, 0,unicode, -1, szUtf8, len, NULL,NULL);
return szUtf8;
} wchar_t* ConvertUtf8ToUnicode(const char* utf8)
{
if(!utf8)
{
wchar_t* buf = (wchar_t*)malloc(2);
memset(buf,0,2);
return buf;
}
int nLen = ::MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,(LPCSTR)utf8,-1,NULL,0);
//返回须要的unicode长度
WCHAR * wszUNICODE = new WCHAR[nLen+1];
memset(wszUNICODE, 0, nLen * 2 + 2);
nLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)utf8, -1, wszUNICODE, nLen); //把utf8转成unicode
return wszUNICODE;
} void change_file_date( const char *filename,uLong dosdate,tm_unz tmu_date)
{
HANDLE hFile;
FILETIME ftm,ftLocal,ftCreate,ftLastAcc,ftLastWrite; wchar_t* filenamew = ConvertUtf8ToUnicode(filename);
hFile = CreateFile(filenamew,GENERIC_READ | GENERIC_WRITE,
0,NULL,OPEN_EXISTING,0,NULL);
GetFileTime(hFile,&ftCreate,&ftLastAcc,&ftLastWrite);
DosDateTimeToFileTime((WORD)(dosdate>>16),(WORD)dosdate,&ftLocal);
LocalFileTimeToFileTime(&ftLocal,&ftm);
SetFileTime(hFile,&ftm,&ftLastAcc,&ftm);
CloseHandle(hFile);
free(filenamew); } int mymkdir(const char* dirname)
{
wchar_t* dirnamew = ConvertUtf8ToUnicode(dirname);
int res = CreateDirectory(dirnamew,NULL);
free(dirnamew);
return res;
} int makedir (const char *newdir)
{
char *buffer ;
char *p;
int len = (int)strlen(newdir); if (len <= 0)
return 0; buffer = (char*)malloc(len+1);
memset(buffer,0,len+1); if (buffer==NULL)
{
printf("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
strcpy(buffer,newdir); if (buffer[len-1] == '/' || 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;
} int do_extract_currentfile(unzFile uf,const int* popt_extract_without_path,
int* popt_overwrite,const char* password,const char* dir)
{
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;
uLong ratio=0;
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;
} std::string dir1(dir);
dir1.append(filename_inzip);
strncpy(filename_inzip,dir1.c_str(),sizeof(filename_inzip)); 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);
}
}
else
{
const char* write_filename;
int skip=0; if ((*popt_extract_without_path)==0)
write_filename = filename_inzip;
else
write_filename = filename_withoutpath; wchar_t* write_filenamew = ConvertUtf8ToUnicode(write_filename);
WrapMalloc wm_filename(write_filenamew);
err = unzOpenCurrentFilePassword(uf,password);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzOpenCurrentFilePassword\n",err);
} if ((skip==0) && (err==UNZ_OK))
{
fout=_wfopen(write_filenamew,L"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 = _wfopen(write_filenamew,L"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<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);
}
}
else
unzCloseCurrentFile(uf); /* don't lose the error */
} free(buf);
return err;
} int do_extract( unzFile uf,
int opt_extract_without_path,
int opt_overwrite,const char* password,const char* dir)
{
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=0;i<gi.number_entry;i++)
{
if (do_extract_currentfile(uf,&opt_extract_without_path,
&opt_overwrite,
password,dir) != UNZ_OK)
return 0; if ((i+1)<gi.number_entry)
{
err = unzGoToNextFile(uf);
if (err!=UNZ_OK)
{
printf("error %d with zipfile in unzGoToNextFile\n",err);
return 0;
}
}
} return 1;
} bool ZipUtil::UnzipFile(std::wstring zip_file,std::wstring unzip_dir)
{
if(unzip_dir[unzip_dir.size()-1] != L'\\')
{
unzip_dir.append(L"\\");
}
int err = UNZ_OK; // error status
uInt size_buf = WRITEBUFFERSIZE; // byte size of buffer to store raw csv data
void* buf; // the buffer
string sout; // output strings
char filename_inzip[256]; // for unzGetCurrentFileInfo
unz_file_info file_info; // for unzGetCurrentFileInfo unzFile uf = UnzOpen64(zip_file.c_str()); // open zipfile stream
if (uf==NULL) {
wcerr << "Cannot open " << zip_file << endl;
return false;
} // file is open
CreateDirectory(unzip_dir.c_str(),NULL);
char* utf8 = ConvertUnicodeToUtf8(unzip_dir.c_str());
int ret_value = do_extract(uf,0,0,NULL,utf8);
unzClose(uf);
free(utf8);
return ret_value;
}
完整项目下载地址:
[zlib]_[0基础]_[使用Zlib完整解压zip内容]的更多相关文章
- [Zlib]_[0基础]_[使用zlib库压缩文件]
场景: 1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言. 2. zlib比較经常使用,编译也方便,使用它来做压缩吧. MacOSX平台默认支持z ...
- [libcurl]_[0基础]_[使用libcurl下载大文件]
场景: 1. 在Windows编程时, 下载http页面(html,xml)能够使用winhttp库,可是并非非常下载文件,由于会失败. 由此引出了WinINet库,无奈这个库的稳定性比較低,使用样例 ...
- [Windows]_[0基础]_[Release程序的崩溃报告minidump解决方式]
场景: 1. Release的程序崩溃时,崩溃报告能够让开发者查明代码哪里出了问题,用处大大的. 2. 仅仅实用VS的编译器才支持,所以MinGW就无缘了. 3. 使用了未处理异常过滤处理函数. 4. ...
- [wxWidgets]_[0基础]_[经常更新进度条程序]
场景: 1. 非常根据程序的进展需要处理业务,以更新进度条,进度条的目的是为了让用户知道业务流程的进度.一个进度条程序更友好,让用户知道在程序执行.不是没有反应. 2. 现在更新见过这两种方法的进展. ...
- [C/C++标准库]_[0基础]_[使用fstream合并文本文件]
场景: 1. 就是合并文本文件,而且从第2个文件起不要合并第一行. 2. 多加了一个功能,就是支持2个以上的文件合并. 3. 问题: http://ask.csdn.net/questions/192 ...
- [ATL/WTL]_[0基础]_[CBitmap复制图片-截取图片-平铺图片]
场景: 1.当你须要截取图片部分区域作为某个控件的背景. 2.须要平铺图片到一个大区域让他自己主动放大时. 3.或者须要合并图片时. 代码: CDC sdc; CDC ddc; sdc.CreateC ...
- [C/C++标准库]_[0基础]_[交集和补集]
场景: 1. 计算std::vector A和 std::vector B里的同样的元素, 用于保留不删除. 2. 计算std::vector A和 std::vector B里各自的补集, 用于删除 ...
- [C/C++标准库]_[0基础]_[优先队列priority_queue的使用]
std::priority_queue 场景: 1. 对于一个任务队列,任务的优先级由任务的priority属性指明,这时候就须要优先级越高的先运行.而queue并没有排序功能,这时priority_ ...
- [网络]_[0基础]_[使用putty备份远程数据]
场景: 1. putty是windows上訪问linux服务的免费client之中的一个.用它来ssh到远程server备份数据是常见的做法(在没做好自己主动备份机制前), 通过putty界面尽管也不 ...
随机推荐
- py文件转exe时包含paramiko模块出错解决方法
问题描述:python代码中包含paramiko模块的远程登录ssh,在用pyInstaller转为exe时报错, 报错提示为“No handlers could be found for logge ...
- javaweb通过接口来实现多个文件压缩和下载(包括单文件下载,多文件批量下载)
原博客地址:https://blog.csdn.net/weixin_37766296/article/details/80044000 将多个文件压缩并下载下来:(绿色为修改原博客的位置) 注意:需 ...
- P3391 【模板】文艺平衡树FHQ treap
P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转 ...
- JAVA-基础(六) Java.serialization 序列化
序 列 化 序列化(serialization)是把一个对象的状态写入一个字节流的过程. Serializable接口 只有一个实现Serializable接口的对象可以被序列化工具存储和恢复.Ser ...
- Linux性能查看
1.TOP top 登录后默认按进程的CPU使用情况排序, 按M则按内存使用排序 2. vmstat 2 2 显示系统负载 3. free -m 查看内存使用情况 4.抓包 tcpdump -i ...
- python - 目录处理
# -*- coding:utf-8 -*- '''@project: jiaxy@author: Jimmy@file: study_文件目录操作.py@ide: PyCharm Community ...
- php isset()与empty()详解
bool isset(mixed var);[;mixed var[,...]] 这个函数需要一个变量名称作为参数,如果这个变量存在,则返回true,否则返回false. 也可以传递一个由逗号间隔的变 ...
- Leetcode 436.寻找右区间
寻找右区间 给定一组区间,对于每一个区间 i,检查是否存在一个区间 j,它的起始点大于或等于区间 i 的终点,这可以称为 j 在 i 的"右侧". 对于任何区间,你需要存储的满足条 ...
- Python循环语句 if while for
流程控制: if 条件1: 缩进的代码块 (注意缩进4个空格) elif 条件2: 缩进的代码块 elif 条件3: 缩进的代码块 ...... else: 缩进的代码块 注意1:(相同的代码块儿,同 ...
- [python学习篇][廖雪峰][1]高级特性 ---迭代
由于字符串也是可迭代对象,因此,也可以作用于for循环: >>> for ch in 'ABC': ... print ch ... A B C 所以,当我们使用for循环时,只要作 ...