redis源碼之字符串壓縮

        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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章