因为面试中腾讯,京东等大公司都有被考到protobuf的知识,我居然只知道xml,json效率比protobuf大大降低,碎研究了下它希望对大家有所帮助!
protobuf的介绍
一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,总体看来ProtoBuf的优势还是很明显的。
protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,详情访问protobuf的google官方网站。
protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。
protobuf简单总结如下几点:
1.灵活(方便接口更新)、高效(效率经过google的优化,传输效率比普通的XML等高很多);
2.易于使用;开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。
3.语言支持;原生支持c++,java,python
数据交互xml、json、protobuf格式比较
1、json: 一般的web项目中,最流行的主要还是json。因为浏览器对于json数据支持非常好,有很多内建的函数支持。
2、xml: 在webservice中应用最为广泛,但是相比于json,它的数据更加冗余,因为需要成对的闭合标签。json使用了键值对的方式,不仅压缩了一定的数据空间,同时也具有可读性。
3、protobuf:是后起之秀,是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。
相对于其它protobuf更具有优势
1:序列化后体积相比Json和XML很小,适合网络传输
2:支持跨平台多语言
3:消息格式升级和兼容性还不错
4:序列化反序列化速度很快,快于Json的处理速速
比较详细的介绍
https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/index.html
上述讲了什么是protobuf以及优点是什么,废话不多说下面我将介绍protobuf具体事例
环境介绍:Linux ubuntu 4.4.0-141-generic #167-Ubuntu SMP Wed Dec 5 10:38:08 UTC 2018 i686 i686 i686 GNU/Linux
1、protobuf安装
apt-get install libprotobuf-dev
2、文件定义test.proto:
mkdir protobuf-test
vi test.proto
message student{
required string name = 1; //姓名
required int32 age = 2; //年龄
optional string sex = 3; //性别
}
//类
message person{
repeated student member = 1; //成员
}
执行命令:protoc ./test.proto --cpp_out=./ 会在当前目录生成两个文件用于序列化数据
3、序列化数据
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fcntl.h>
#include <fstream>
#include <cstdio>
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include "test.pb.h"
using namespace std;
int main(int argc, char** argv)
{
if (argc <2){
printf("programe savefile\n");
exit(1);
}
person c;
//添加学生
student* t = c.add_member();
t->set_name("Toy");
t->set_age(21);
t->set_sex("boy");
t = c.add_member();
t->set_name("jack");
t->set_age(25);
t->set_sex("boy");
t = c.add_member();
t->set_name("lili");
t->set_age(20);
t->set_sex("girl");
//首先将protobuf输出到一个string中
std::string p;
google::protobuf::TextFormat::PrintToString(c,&p);
//输出到文件中
ofstream fout;
fout.open(argv[1], ios::out| ios_base::ate);
if (!fout.is_open()){
fprintf(stderr, "open %s fail\n", argv[1]);
return -1;
}
fout <<p<<endl;
fout.flush();
fout.close();
return 0;
}
编译:g++ proto-write.cc test.pb.cc -lprotobuf -o proto-write
结果:
4、读取解析
#include "test.pb.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fcntl.h>
#include <fstream>
#include <cstdio>
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
using namespace std;
int main(int argc, char** argv)
{
if (argc <2){
printf("programe reloadfile\n");
exit(1);
}
person c;
int fileDescriptor = open(argv[1], O_RDONLY);
if( fileDescriptor < 0 ){
return -1;
}
google::protobuf::io::FileInputStream fileInput(fileDescriptor);
fileInput.SetCloseOnDelete( true );
if (!google::protobuf::TextFormat::Parse(&fileInput, &c)){
return -2;
}
cout<<"student number:"<<c.member_size()<<endl;
for (int i = 0 ; i < c.member_size(); i++){
cout <<"student name:"<<c.member(i).name()<<endl;
cout <<"student age:" << c.member(i).age()<<endl;
cout <<"student sex:" << c.member(i).sex() <<endl;
}
return 0;
}
编译:
g++ proto-read.cc test.pb.cc -lprotobuf -o proto-read
结果: