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