[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界面尽管也不 ...
随机推荐
- BZOJ 4896: [Thu Summer Camp2016]补退选
trie树+vector+二分 别忘了abs(ans) #include<cstdio> #include<algorithm> #include<vector> ...
- HDU 5528 Count a * b 欧拉函数
题意: 定义函数\(f(n)\)为\(i \cdot j \not\equiv 0 \; (mod \; n)\)的数对\((i,j)\)的个数\((0 \leq i,j \leq n)\) \(g( ...
- 大数据学习——actor编程
1 概念 Scala中的Actor能够实现并行编程的强大功能,它是基于事件模型的并发机制,Scala是运用消息(message)的发送.接收来实现多线程的.使用Scala能够更容易地实现多线程应用的开 ...
- python - 接口自动化测试 - ReadExcel - 读取测试数据封装
# -*- coding:utf-8 -*- ''' @project: ApiAutoTest @author: Jimmy @file: read_excel.py @ide: PyCharm C ...
- JS进行人民币大小写转换
//数字金额大写转换(可以处理整数,小数,负数) function upDigit() { digit=$("#digit").html(); n=digit.replace(/\ ...
- 一个关于python装饰器参数的问题
看到廖雪峰python教程上,python装饰器一章 https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3 ...
- 近期JS心得
child和tags都是[{id:1,value:'a'}]的格式,当点击一级标签,要看二级标签是否已经被选中,如果被选中,则清除出去 如果用for循环 再splice的话 当删除掉了一个元素后,数组 ...
- Java面试题之final、finally和finalize的区别
final: final是一个修饰符,可以修饰变量.方法和类,如果final修饰变量,意味着变量的值在初始化后不能被改变: 防止编译器把final域重排序到构造函数外:(面试的时候估计答出这个估计会加 ...
- base642photo
/** * pic to base64Str * @param path 读取路径 * @return */ public static String GetIm ...
- 【SCOI2003】【BZOJ1092】蜘蛛难题
有一堆管道,还有一个蜘蛛Willy,如下图所示.所有管道的是上端开口,下端封底,直径都是1cm,连接两个管道的连接容量无限,但体积可以忽略不计. 在第一个管道上方有一个水源,从中有水不断往下流,速度为 ...