基于Zlib实现的从ZIP文件中提取文件数据
来源:互联网 发布:js拖动滑块验证条 编辑:程序博客网 时间:2024/06/05 00:53
前言:呃,今天上来翻了翻之前写的文章,其中访问率最高的是那个『自绘RadioButton』,有好多人留言让我发源代码,这,也是自己懒惰,现在已经把源代码的连接补到文章最后,也是CSDN的下载,希望对某些人有帮助吧,呵呵。看着之前自己写的东西还挺有意思的,特别是那个用JAVA做的地图编辑器的学习版,其实是到后面写不下去了,觉得越想越复杂。其实自己最近闲暇时分用MFC写了个『Descent: Journey To The Dark!』的地图编辑器,下次整理整理发上来好了。这几年因为工作一直很忙,说实话也没啥多的技术积累,毕竟公司里面混饭吃,还是要做一些杂活,虽然感觉也做得久了点。好了,言归正传,这次的东西是关于从ZIP压缩包中读取文件的方法。其实也是那个地图编辑器要用的一个小功能。使用了Zlib库中contrib中的minizip的代码,有兴趣的童鞋可以去下Zlib源码看下,我是没这个闲情雅致,只是实用派的。之前也在网上搜了好久,大多都是介绍如何使用Zlib库压缩和解压数据,唯独就是没几多人介绍如何从ZIP Archive中抽取文件的。不过也可能是我太急功近利了,只是想找抽取的代码,而不想一步一步看人家的介绍。正好昨天找了点资料,自己捣鼓了下,把这抽取的代码写了下,可能有些人也正急着找也不一定(当然,我觉得像我这种从头写地图编辑器的奇葩估计也不多了,网上大把的类库可以用)。不过也正好,把抽取的方法写成了个动态库,还做了lua的封装导出,这样C++和Lua就都能用了,写得比较简单,只是介绍个方法,其他功能还有待扩展,这里只是个例子可以参考下实现的方案,因为代码中好多都是测试用的,并且错误处理基本没有做,以后再慢慢完善吧。代码随便用,本来就是个测试版的东西,出事儿了别找我就行。
平台
源代码略解
// The following ifdef block is the standard way of creating macros which make exporting // from a DLL simpler. All files within this DLL are compiled with the ZEXTRACT_EXPORTS// symbol defined on the command line. this symbol should not be defined on any project// that uses this DLL. This way any other project whose source files include this file see // ZEXTRACT_API functions as being imported from a DLL, wheras this DLL sees symbols// defined with this macro as being exported.#ifdef ZEXTRACT_EXPORTS#define ZEXTRACT_API __declspec(dllexport)#else#define ZEXTRACT_API __declspec(dllimport)#endif#include "MemBuffer.h"#include "luna.hpp"ZEXTRACT_API void ListZip(const char* fname);ZEXTRACT_API bool FindFileInZip(const char* zfn, const char* fname);ZEXTRACT_API int GetFileInZip(CMemBuffer& buffer, const char* zfn, const char* fname, const char* password);extern "C" ZEXTRACT_API int luaopen_zextract(lua_State* L);讲下GetFileInZip函数。一共有4个入参:
- CMemBuffer对象,用来存储从压缩包中抽取的文件。
- 对应的ZIP Archive文件路径,相对路径和绝对路径皆可。
- 对应在ZIP Archive中要提取的文件路径。
- 密码,如果没有密码则填NULL或者0即可。
zextract.cpp::GetFileInZip
ZEXTRACT_API int GetFileInZip(CMemBuffer& buffer, const char* zfn, const char* fname, const char* password){unzFile uf = unzOpen(zfn);if (NULL == uf){printf("unzOpen failed...\n");return -1;}int err = unzLocateFile(uf, fname, 0);if (UNZ_OK != err){printf("GetFileInZip unzLocateFile failed... error:%d\n");return err;}unz_file_info file_info;char filename_inzip[256];err = unzGetCurrentFileInfo(uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);if (UNZ_OK != err){printf("unzGetCurrentFileInfo failed... error:%d\n", err);return err;}err = unzOpenCurrentFilePassword(uf, password);if (UNZ_OK != err){printf("unzOpenCurrentFilePassword failed... error:%d\n", err);return err;}char* pBuff = new char[file_info.uncompressed_size];if (pBuff == NULL){unzCloseCurrentFile(uf);unzClose(uf);return -2;}err = unzReadCurrentFile(uf, pBuff, file_info.uncompressed_size);if (err < 0){printf("unzReadCurrentFile failed... error:%d\n", err);delete [] pBuff;unzCloseCurrentFile(uf);unzClose(uf);return err;}// Append data to the MemBufferbuffer.Append(pBuff, file_info.uncompressed_size);unzCloseCurrentFile(uf);unzClose(uf);return err;}其中关键的操作函数就只有7个:
CMemBuffer
// MemBuffer.h: interface for the CMemBuffer class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_MEMBUFFER_H__36D0136D_B57A_49FF_855B_E5545078B130__INCLUDED_)#define AFX_MEMBUFFER_H__36D0136D_B57A_49FF_855B_E5545078B130__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000class CMemBuffer {public:CMemBuffer(int nInitLen = 16);CMemBuffer(const char* pData, int nLen = 0);CMemBuffer(const CMemBuffer& buff);virtual ~CMemBuffer();public:virtual int GetBufferLen();virtual bool Append(const char* pData, int nLen = 0);virtual char* GetBuffer();protected:bool ReAllocBuffer(int nDeltaLen);protected:char* m_pBuffer;// buffer dataint m_nCurLen;int m_nMaxLen;};#endif // !defined(AFX_MEMBUFFER_H__36D0136D_B57A_49FF_855B_E5545078B130__INCLUDED_)这个实现没什么好讲的,拿到数据只要Append即可。要获取数据直接使用GetBuffer()即可。
Lua导出部分
//////////////////////////////////////////////////////////////////////////// @Param// zipName which archive// fileName which file to extract from the archive named zipName's value// password password to extract file from zip// @Return// binary data// error numberstatic int luacf_getFileInZip(lua_State* L){CMemBuffer buff;const char* pZipName = luaL_checkstring(L, 1);const char* pFileName = luaL_checkstring(L, 2);const char* pPassword = lua_tostring(L, 3);int ret = GetFileInZip(buff, pZipName, pFileName, pPassword);if (ret >= 0){lua_pushlstring(L, buff.GetBuffer(), buff.GetBufferLen());return 1;}lua_pushnil(L);lua_pushnumber(L, ret);return 2;}const struct luaL_reg libs[] ={{"getFileInZip", luacf_getFileInZip},{NULL, NULL}};ZEXTRACT_API int luaopen_zextract(lua_State* L){luaL_register(L, "zextract", libs);return 1;}这部分就没啥好说了,总之就是这么简单。
Lua测试代码
-- 是否是debug版本local bDGB = false;local zlib;if bDGB thenzlib = package.loadlib("zextract_d.dll", "luaopen_zextract");if type(zlib) == "function" thenzlib = zlib();endelsezlib = require "zextract";endif type(zlib) ~= "table" thenprint("loadlib error");returnendprint(zlib.getFileInZip("readme.zip", "folder/readme.txt", "123456"))
这里要讲下对应的载入,前面有个debug版本的判断,这个是根据当前编译的版本决定的,当然也可以debug和release版本都编译,名字是不同的,到时候自己手动修改下这个bDGB的标志即可。二进制的文件就不要用这个代码了,因为最后的数据是print出来的,文本的能看下。载入动态库的部分可以看下之前的文章《Lua脚本调用C++动态库》
目录结构
- 基于Zlib实现的从ZIP文件中提取文件数据
- 基于Zlib实现的从ZIP文件中提取文件数据
- 从ZIP文件中解压缩和提取数据
- Zlib库的使用实现对zip文件的解压缩
- zlib 解压zip文件
- 从zip文件中读取数据
- 从zip文件中读取数据
- 怎样从wav文件中提取记录频率的数据
- C++ 从文件中提取序列数据
- 从文件中提取Json数据
- 从url中提取文件的扩展名
- Zlib库的使用实现对zip文件的解压缩(二)
- VC中使用zlib压缩目录结构生成zip文件
- php实现从mysql备份sql文件中提取特定数据
- 从文件中提取数字
- MATLAB之从fig文件中提取数据
- 怎样从MATLAB图形文件fig中提取数据
- 实现--从文件中随机提取一个字符串
- 一道思考题
- 网站排名优化推广方案存在的必然性
- 消除Key Lookup和RID Lookup Part1:使用Include Index
- 20120801-51 单片机计数器T1计数外部脉冲
- mysql distinct 用法详解及优化
- 基于Zlib实现的从ZIP文件中提取文件数据
- SQL之group by order by 和多字段的理解和联想
- struts2的路径问题
- Android游戏开发之数据库SQLite 详细介绍(十七)
- Linux 系统内核的调试
- 一定要坚强
- 自建AP wifi
- HDU - 4324 Triangle LOVE
- Delphi中TApplication类的巧用