Er, I have reviewed my previous articles today. The highest attention rate is the "self-painted radiobutton". Many people have sent messages to send source code, which is also lazy, now the source code connection has been added to the end of the article, and it is also the download of csdn. I hope it will help some people. Looking at what I wrote before is quite interesting, especially the learning version of the map editor made of Java, which is actually not written in the future, and I think the more complicated it is. In fact, I recently used MFC to write "Descent: Journey to the dark!" in my spare time !』 The map editor. It will be sorted and sent up next time. Over the past few years, I have been very busy with my work. To tell the truth, I have not accumulated much technical experience. After all, I still want to do some chores in the company, even though I have been doing it for a long time. Now, let's get to the point. This is about how to read files from a zip package. It is actually a small function used by the map editor. I used the minizip code in the contrib In the zlib library. If you are interested, you can go to the zlib source code and check it out. I don't have this kind of elegance, but it's just practical. I 've been searching for it on the internet for a long time. Most of them are about how to use the zlib library to compress and decompress data, but few people have introduced how to use the zip
Archive. However, it may be that I am too eager for immediate benefits. I just want to find the extracted code, rather than looking at the introduction step by step. Just yesterday, I found some information, and I tried to write the extracted code. Some people may not be eager to find it (of course, I don't think there are many wonderful ideas about writing a map editor from the ground up like me. I can use a lot of class libraries on the Internet ). However, the extraction method is written into a dynamic library, and Lua encapsulation and export are also implemented, so that both C ++ and Lua can be used and the writing is relatively simple, I just introduced a method, and other functions are to be extended. Here is just an example to refer to the implementation scheme, because many of the code is used for testing and error handling is basically not done, I will try again later. The code can be used at will. It was originally a test version. If something happens, don't look for me.
Platform programs are compiled using vc6.0 on Windows (XP and win7. The people who want to use vs should turn around on their own. The internal implementation is like this, and there is no use of MFC. The program uses the zlib library. The version is 1.2.3. Lua is also used. The version is 5.1.4, but you don't need Lua. I did it by the way and didn't try to remove it myself. In the source code, the zextract project is better. In fact, only three functions are implemented, and only two functions are reliable. Only one of them is practical. They are 1. "list files in the compressed package", 2. "Find Files in the compressed package", and 3. "Get files in the compressed package 』. The first one is obviously fun, because printf is directly output to the console, and it also refers to the implementation of the do_list function in minizip. The second function is written, but it is useless. It is mainly for fun. The last one is useful for reading files from a compressed package, and the cmembuffer class is also used. Let's take a look at the header file of the project.
// 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);
LectureGetfileinzipFunction. There are a total of four input parameters:
- CmembufferObject used to store the files extracted from the compressed package.
- The corresponding ZIP archive file path, both relative and absolute paths.
- Corresponding to the file path to be extracted in the ZIP archive.
- Password. If there is no password, enter null or 0.
If the return value is greater than or equal to 0, it indicates the size of the extracted file. If the return value is less than 0, it is the corresponding error code. If the execution is successful, the file content is stored in the buffer object. There is no need to introduce the remaining two functions. You just need to check the source code. 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;}
Among them, there are only 7 key operation functions:
Unzopen |
Open the archive file |
Unzclose |
Close archive files |
Unzgetcurrentfileinfo |
Obtains information about the selected internal compressed file. |
Unzlocatefile |
Locate a file |
Unzopencurrentfilepassword |
Select to open the current file |
Unzreadcurrentfile |
Read current file |
Unzclosecurityfile |
Close current file |
The last three must be used in combination. That is to say, to read an internal file, you must first open the file, then read the file, and finally close the file. There are many methods to select the current file. Here we use the unzlocatefile function. If the corresponding file is found, this file will be selected as the current file by default. For more information about the listzip function implementation code, see. The cmembuffer class only implements the function of storing memory data. There are many considerations for using a class to store file data. For example, if a file is binary-an image, or if the data is obtained from the heap memory, you need to consider the issue of releasing yourself. Manual management is obviously troublesome. It is better to create a cache class to manage these memory data blocks.
// 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_)
There is nothing to say about this implementation. You only need to append the data to get it. Directly useGetbuffer. Lua export part
//////////////////////////////////////////////////////////////////////////// @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;}
There is nothing to say about this part. In short, it is so simple. Lua test code
-- Whether the debug version is 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 "))
Here we will talk about the corresponding loading. The previous debug version is determined based on the current compiled version. Of course, both Debug and release versions can be compiled, the name is different. You can manually modify the bdgb logo. Do not use this code for binary files, because the final data is printed and the text can be viewed. To load the dynamic library, you can download the source code of the previous article "Lua script calls C ++ dynamic library. The directory structure consists of five folders. The project directory of the dynamic library is in the zextract folder. The zlibtest directory is a project file that calls zextract to generate a dynamic library. The lib directory is the directory of the corresponding library file, including the zlib library file and the library file generated by the zextract dynamic library. Comm files are some public file storage areas, such as the minizip implementation source code and the memory buffer implementation source code. . There is also a Lua file for test export and warehouse picking.