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