redis源码之字符串压缩

mac2026-01-09  7

        redis关于字符串压缩的几个文件分别是:lzf.h,lzfP.h,lzf_c.c,lzf_d.c,下面看一个测试用例。

#include <iostream> #include <string> #include "lzfP.h" #include "lzf.h" using namespace std; int main() { string value = "hello world hello world hello world hello world"; size_t len = value.size(); // 字符串未压缩前的长度 cout << "压缩前:val = " << value << endl; cout << "压缩前:len = " << len << endl << endl; // -------------------压缩--------------------------------- size_t comprlen; // 压缩后的长度 size_t outlen; // 输出缓存的最大长度 unsigned char byte; int n, nwritten = 0; void *out; /* We require at least four bytes compression for this to be worth it */ if (len <= 4) { cout << "len <= 4" << endl; return 0; } outlen = len-3; if ((out = malloc(outlen+1)) == NULL) { cout << "out = malloc(outlen+1)" << endl; return 0; } comprlen = lzf_compress(value.data(), len, out, outlen); if (comprlen == 0) { cout << "outlen == " << outlen << endl; cout << "comprlen == 0" << endl; free(out); return 0; } cout << "压缩后:val = " << out << endl; cout << "压缩后:len = " << comprlen << endl << endl; // -------------------解压缩--------------------------------- char *val = NULL; // 字符串空间 if ((val = (char*)malloc(len)) == NULL) { cout << "lzf_decompress" << endl; return 0; } // 解压,得出字符串 if (lzf_decompress(out, comprlen, val, len) == 0) { cout << "lzf_decompress" << endl; return 0; } cout << "解压后:val = " << val << endl; cout << "解压后:len = " << len << endl; free(out); free(val); getchar(); getchar(); getchar(); getchar(); return 0; }

运行结果:

mapan@mapan-virtual-machine:~/c++/zifuc$ ./a.out 压缩前:val = hello world hello world hello world hello world 压缩前:len = 47 压缩后:val = 0x55fd0a5322c0 压缩后:len = 20 解压后:val = hello world hello world hello world hello world 解压后:len = 47

压缩之后的长度变为20了,成功压缩。改变被压缩的字符再看。

如:string value = "qwertyuiopasdfghjklzxcvbnm"; 

mapan@mapan-virtual-machine:~/c++/zifuc$ ./a.out 压缩前:val = qwertyuiopasdfghjklzxcvbnm 压缩前:len = 26 outlen == 23 comprlen == 0

未被压缩成功,表明压缩的结果不符合预期,所以直接返回失败了。压缩时,程序传入的长度时outlen = len-4;现在用同样的字符串,让outlen = len + 5;

mapan@mapan-virtual-machine:~/c++/zifuc$ ./a.out 压缩前:val = qwertyuiopasdfghjklzxcvbnm 压缩前:len = 26 压缩后:val = 0x563f9561c2b0 压缩后:len = 27 解压后:val = qwertyuiopasdfghjklzxcvbnm 解压后:len = 26

现在压缩成功了,传入outlen,是out_data对应的大小,当压缩后的长度大于outlen,自然返回失败。

说到压缩字符串就会让人想到序列化,序列化也是一种压缩,方便跨平台传输数据,解决了对象引用的问题,如protobuff。下面看一个例子。

为什么要序列化详细见:https://blog.csdn.net/u010178308/article/details/80411848

msg.proto

package demo; message msg { required int32 msgtype=1; required string msginfo=2; required string msgfrom=3; optional string opt=4; //can select }

protobuff_demo.cc

代码地址:https://blog.csdn.net/kai8wei/article/details/62230878

#include"msg.pb.h" #include<iostream> #include<string> using namespace std; int main(int argc,char *argv[]) { demo::msg writer; writer.set_msgtype(1); //设置数据 writer.set_msginfo("i am weeks");//设置数据 writer.set_msgfrom("127.0.0.1");//设置数据 //C++string序列化和序列化API //客户端格式化信息 string in_data; writer.SerializeToString(&in_data); //序列化 //下面用一个临时的string 表示在网络中进行传输的过程 //真是的过程中你可以借助相应的网络框架对数据进行传输 //客户端将数据放到网络上 string tmp=in_data; //服务端从网络上拿数据 string out_data=tmp; //服务端反格式化信息 demo::msg reader; reader.ParseFromString(out_data); //解序列化 cout<<"msg_type: "<<reader.msgtype()<<endl; cout<<"msg_info: "<<reader.msginfo()<<endl; cout<<"msg_from: "<<reader.msgfrom()<<endl; return 0; }

执行:protoc --cpp_out=. msg.proto   (会生成msg.pb.h)

           g++ protobuff_demo.cc msg.pb.cc -lprotobuf

运行可执行文件:

mapan@mapan-virtual-machine:~/c++/redis/proto$ ./a.out msg_type: 1 msg_info: i am weeks msg_from: 127.0.0.1

 

最新回复(0)