使用zlib压缩解压并导出lua接口

网络游戏在前后端交换的过程中,有可能会有大量的数据,比如说游戏回放功能,这时最好是将数据压缩一下。

比较简单的数据压库就是zlib了。

zlib官方文档,常用的函数都在这里了,解释很详细。

一  C++功能实现部分

下面将代码贴上来。

在ZipUtils中添加下面三个函数:

// ZipUtils.h

 <pre name="code" class="cpp">typedef struct{
	unsigned str_size;
	unsigned buf_size;
	char data[];// 柔性数组
}CompressedData;

class ZipUtils
 {
    public:
		// add by XuLidong
		static void testFun();
		static unsigned getCompressBound(unsigned len);
		static bool compressString(const char* str,CompressedData* pdata);
		static bool decompressString(CompressedData* pdata, char* str);
};

用到了柔性数组,不动的可以参考我的另一篇文章

下面是相应的实现:

// ZipUtils.cpp

#include <zlib.h>
#include <stdlib.h>
#include "ZipUtils.h"

int test1()
{
	char text[] = "zlib compress and uncompress test\[email protected]\n2012-11-05\n";
	uLong tlen = strlen(text) + 1;  /* 需要把字符串的结束符'\0'也一并处理 */
	char* buf = NULL;
	uLong blen;  

	/* 计算缓冲区大小,并为其分配内存 */
	blen = compressBound(tlen); /* 压缩后的长度是不会超过blen的 */
	printf("compress str_size:%d, buf_size:%d\n", tlen, blen);
	if((buf = (char*)malloc(sizeof(char) * blen)) == NULL)
	{
		printf("no enough memory!\n");
		return -1;
	}  

	/* 压缩 */
	if(compress((Bytef*)buf, &blen, (const Bytef*)text, tlen) != Z_OK)
	{
		printf("compress failed!\n");
		return -1;
	}  

	/* 解压缩 */
	printf("uncompress str_size:%d, buf_size:%d\n", tlen, blen);
	if(uncompress((Bytef*)text, &tlen, (const Bytef*)buf, blen) != Z_OK)
	{
		printf("uncompress failed!\n");
		return -1;
	}  

	/* 打印结果,并释放内存 */
	printf("%s", text);
	if(buf != NULL)
	{
		free(buf);
		buf = NULL;
	}
}

void test2()
{
	const char* str="abcdefg 中文字符可以吗 ? 》 , >\ ";
	unsigned len = strlen(str) + 1;
	unsigned long blen = compressBound(len);
	CompressedData* pdata = (CompressedData*)malloc(sizeof(CompressedData) + blen * sizeof(char));
	pdata->str_size = len;
	pdata->buf_size = blen;
	ZipUtils::compressString(str, pdata);

	char* ustr = (char*)malloc(len);
	memset(ustr, 0, len);
	ZipUtils::decompressString(pdata, ustr);

	free(ustr);
}

void ZipUtils::testFun()
{
	//test1();
	test2();
}

unsigned ZipUtils::getCompressBound(unsigned len)
{
	return (unsigned)compressBound((unsigned long)len);
}

bool ZipUtils::compressString(const char* str, CompressedData* pdata)
{
	printf("compress string:%s\n", str);
	int res = compress((Bytef*)pdata->data, (unsigned long*)&(pdata->buf_size), (const Bytef*)str, (unsigned long)pdata->str_size);
	if( res != Z_OK)
	{
		printf("compress failed, error code:%d\n", res);
		return false;
	}
	printf("string size %d, buffer size: %d\n", pdata->str_size, pdata->buf_size);

	return true;
}

bool ZipUtils::decompressString(CompressedData* pdata, char* str)
{
	printf("string size %d, buffer size: %d\n", pdata->str_size, pdata->buf_size);
	int res = uncompress((Bytef*)str, (unsigned long *)&(pdata->str_size), (const Bytef *)pdata->data, (unsigned long)pdata->buf_size);
	if(res != Z_OK)
	{
		printf("uncompress failed, error code:%d\n", res);
		return false;
	}
	printf("uncompress string:%s\n", str);

	return true;
}

二 C++导出到Lua接口

// ZipUtilsLua.h

#include "tolua++.h"
#include "tolua_event.h"
#include "lauxlib.h"

int tolua_ZipUtils_open(lua_State *L);

// ZipUtilsLua.cpp

#include "support/zip_support/ZipUtils.h"
#include <string>

#include "tolua++.h"
#include "tolua_event.h"
#include "lauxlib.h"

using namespace cocos2d;

int TOLUA_API luaCopressString(lua_State *L)
{
	size_t slen = 0;
	const char *str = lua_tolstring(L, 1, &slen);
	unsigned blen = ZipUtils::getCompressBound((unsigned long)slen);
	CompressedData* pdata = (CompressedData*)malloc(sizeof(CompressedData) + blen * sizeof(char));
	pdata->str_size = slen;
	pdata->buf_size = blen;
	if(ZipUtils::compressString(str, pdata)){
		lua_pushlstring(L, (char*)pdata, pdata->buf_size+sizeof(CompressedData));
		printf("sizeof=%d", sizeof(CompressedData));
	}
	else{
		lua_pushstring(L, "");
	}
	free(pdata);

	return 1;
}

int TOLUA_API luaDecopressString(lua_State *L)
{
	const char *strBuf = lua_tostring(L, 1);
	CompressedData* pdata = (CompressedData*)strBuf;
	unsigned slen = pdata->str_size;
	unsigned blen = pdata->buf_size;

	char* str = (char*)malloc(pdata->str_size * sizeof(char));
	if(ZipUtils::decompressString(pdata, str)){
		lua_pushlstring(L, str, slen);
	}
	else{
		lua_pushstring(L, "");
	}

	free(str);

	return 1;
}

int TOLUA_API luaTestFun(lua_State *L)
{
	ZipUtils::testFun();

	return 1;
}

static luaL_Reg ziplib[] = {
	{"compress", luaCopressString},
	{"decompress", luaDecopressString},
	{"testFun", luaTestFun},
	{NULL, NULL}
};

// 函数名必须为luaopen_xxx,其中xxx表示library名称,Lua代码require "xxx"需要与之对应。
int luaopen_ZipUtils(lua_State* L)
{
	const char* libName = "ZipUtils";
	luaL_register(L, libName, ziplib);// 调用方式libName.函数名

	return 1;
}

int tolua_ZipUtils_open(lua_State *L)
{
	luaopen_ZipUtils(L);
	return 1;
}

注册代码:

    // register lua engine
    CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
    CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
    <span style="font-family: Arial, Helvetica, sans-serif;">tolua_ZipUtils_open</span><span style="font-family: Arial, Helvetica, sans-serif;">(pEngine->getLuaStack()->getLuaState());</span>

三 Lua中调用

	require ("ZipUtils")

	local string = "hello, world"
	local zipData = ZipUtils.compress(string)
	if c ~= "" then
		print("XXXXXXXXXXXXXXXXX compress", zipData)
	else
		print("XXXXXXXXXXXXXXXXX error")
	end
	local str = ZipUtils.decompress(zipData)
	if str ~= "" then
		print("XXXXXXXXXXXXXXXXX decompress", str)
	else
		print("XXXXXXXXXXXXXXXXX error")
	end	
时间: 2025-01-02 01:13:16

使用zlib压缩解压并导出lua接口的相关文章

python zlib 压缩 解压 文件夹

import os,os.path import zipfile def zip_dir(dirname,zipfilename): filelist = [] if os.path.isfile(dirname): filelist.append(dirname) else : for root, dirs, files in os.walk(dirname): for name in files: filelist.append(os.path.join(root, name)) zf =

[原]使用SevenZipSharp压缩/解压7z格式

7z格式采用的LZMA算法,号称具有现今最高压缩率.笔者在nuget上搜索7z,在搜索结果中最终选择了SevenZipSharp来进行压缩/解压.不得不说,SevenZipSharp的API设计得非常方便. 压缩调用: using (FileStream ostream = new FileStream(outputpath, FileMode.Create, FileAccess.Write)) { using (FileStream istream = new FileStream(inpu

PHP扩展类ZipArchive实现压缩解压Zip文件和文件打包下载

PHP扩展类ZipArchive实现压缩解压Zip文件和文件打包下载 http://my.oschina.net/junn/blog/104464 PHP ZipArchive 是PHP自带的扩展类,可以轻松实现ZIP文件的压缩和解压,使用前首先要确保PHP ZIP 扩展已经开启,具体开启方法就不说了,不同的平台开启PHP扩增的方法网上都有,如有疑问欢迎交流.这里整理一下常用的示例供参考. 一.解压缩zip文件 ? 1 2 3 4 5 6 7 8 9 10 11 $zip = new ZipAr

接口测试(八)--压缩解压

今天认识了一位很有名的老中医,与之闲聊.他问我做什么的,我说:做软件测试的.当听到我的职业之后,他建议我:做你们这一行,夏天尽量不要开空调,多运动,少吃冰淇淋,不要经常买饮料喝,不能喝啤酒,更不能喝红酒,多喝白开水,出门应该少打车多坐公交或步行,不要在外面吃饭,尽量吃素,少吃肉类,特别是海鲜! 我点了点头,老中医接着说 :毕竟,你们收入太低了- 我竟然无言以对.. ---------------------------进入正题--------------------------- 一.什么是HT

WebAPI性能优化之压缩解压

有时候为了提升WebAPI的性能,减少响应时间,我们会使用压缩和解压,而现在大多数客户端浏览器都提供了内置的解压支持.在WebAPI请求的资源越大时,使用压缩对性能提升的效果越明显,而当请求的资源很小时则不需要使用压缩和解压,因为压缩和解压同样也是需要耗费一定的时间的. 看见老外写了一篇ASP.NET Web API GZip compression ActionFilter with 8 lines of code 说实话被这标题吸引了,8行代码实现GZip压缩过滤器,我就照着他的去实践了一番

Lniux常见的压缩/解压命令小结

转载请注明: 导航制导与控制实验室 2014年12月16日 在linux开发过程中,经常会遇资料的打包/解包.压缩/解压:本文我将在linux系统中常用的命令进行了整理和分类,内容如下: 1.tar 命令,主要是对Dir先归档,在借助其他命令处理归档文件: 2.单个文件的压缩命令,对单个文件进行处理的命令,有时也可以借助tar命令对目录先打包,再进行压缩: 3.zip.rar压缩命令,即可对单个文件也可对目录进行压缩处理,该方法利于不同操作系统的处理: 该文章只是作者本人的理解,有些命令还会验证

压缩&amp;&amp;解压命令汇总

以下是搜集的Linux系统下,压缩&&解压命令,以备参考使用. .tar 解包: tar xvf FileName.tar 打包:tar cvf FileName.tar DirName    tar cvf a.tar a.txt b.txt c.txt (注:tar是打包,不是压缩!) --------------------------------------------- .gz 解压1:gunzip FileName.gz 解压2:gzip -d FileName.gz 压缩:g

支持文件的流式压缩/解压IP*Works! Zip

IP*Works! Zip是为应用程序添加压缩功能的完全可控件组件包.使用简单.速度快并且效率很高,是一个为桌面和网上应用程序添加压缩和解压缩功能的组件套包./n software IP*Works! Zip支持Zip.Tar.Gzip 和 Jar压缩标准,特别的,它支持流式压缩.加密压缩,在压缩包里就可以直接删除文件.我们目前提供完全可控的纯C# .NET组件.纯Java Beans. 产品特征: IP*Works! Zip基于纯C#代码,是完全可控的.NET组件,不依赖于任何外部代码.是完全

Lucene4.2源码解析之fdt和fdx文件的读写——fdx文件存储一个个的Block,每个Block管理着一批Chunk,通过docID读取到document需要完成Segment、Block、Chunk、document四级查询,引入了LZ4算法对fdt的chunk docs进行了实时压缩/解压

前言 通常在搜索打分完毕后,IndexSearcher会返回一个docID序列,但是仅仅有docID我们是无法看到存储在索引中的document,这时候就需要通过docID来得到完整Document信息,这个过程就需要对fdx/fdt文件进行读操作.为了更清楚地了解fdx/fdt文件的作用,本文把fdx/fdt文件的读和写整合到了一起,尽管这在Lucene中是两个分开的过程. 1. 索引生成阶段 索引生成阶段包含着一个复杂的过程,所以了解本文前最好对Lucene的索引架构有一定的了解,可以参考博