Google Protocol Buffer的学习精要
来源:互联网 发布:互联网金融淘宝 编辑:程序博客网 时间:2024/06/06 21:04
基础知识
- 在 protobuf 的术语中,结构化数据被称为 Message
- a
基本结构
清单 1. proto 文件
package lm; message helloworld { required int32 id = 1; // ID required string str = 2; // str optional int32 opt = 3; //optional field }
编译 .proto 文件
写好 proto 文件之后就可以用 Protobuf 编译器将该文件编译成目标语言了。本例中我们将使用 C++。
假设您的 proto 文件存放在 $SRC_DIR 下面,您也想把生成的文件放在同一个目录下,则可以使用如下命令:
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
命令将生成两个文件:
lm.helloworld.pb.h , 定义了 C++ 类的头文件
lm.helloworld.pb.cc , C++ 类的实现文件
在生成的头文件中,定义了一个 C++ 类 helloworld,后面的 Writer 和 Reader 将使用这个类来对消息进行操作。诸如对消息的成员进行赋值,将消息序列化等等都有相应的方法。
编写 writer 和 Reader
需求:
Writer 将把一个结构化数据写入磁盘,以便其他人来读取。假如我们不使用 Protobuf,其实也有许多的选择。一个可能的方法是将数据转换为字符串,然后将字符串写入磁盘。
使用字符串缺点:
但是仔细考虑一下就会发现,这样的做法对写 Reader 的那个人的要求比较高,Reader 的作者必须了 Writer 的细节。比如”123”可以是单个数字 123,但也可以是三个数字 1,2 和 3。
使用 Protobuf优势:
如果使用 Protobuf,那么这些细节就可以不需要应用程序来考虑了。
1. 需要处理的结构化数据由 .proto 文件描述;
2. Writer 需要 include 该头文件,然后便可以使用这个类了。
使用
经过上一节中的编译过程后,该数据化结构对应了一个 C++ 的类,并定义在 lm.helloworld.pb.h 中。对于本例,类名为 lm::helloworld。
在 Writer 代码中,将要存入磁盘的结构化数据由一个 lm::helloworld 类的对象表示,它提供了一系列的 get/set 函数用来修改和读取结构化数据中的数据成员,或者叫 field。
过程
当我们需要将该结构化数据保存到磁盘上时,类 lm::helloworld 已经提供相应的方法来把一个复杂的数据变成一个字节序列,我们可以将这个字节序列写入磁盘。
对于想要读取这个数据的程序来说,也只需要使用类 lm::helloworld 的相应反序列化方法来将这个字节序列重新转换会结构化数据。这同我们开始时那个“123”的想法类似,不过 Protobuf 想的远远比我们那个粗糙的字符串转换要全面,因此,我们不如放心将这类事情交给 Protobuf 吧。
清单 2. Writer 的主要代码
#include "lm.helloworld.pb.h"… int main(void) { lm::helloworld msg1; msg1.set_id(101); msg1.set_str(“hello”); // Write the new address book back to disk. fstream output("./log", ios::out | ios::trunc | ios::binary); if (!msg1.SerializeToOstream(&output)) { cerr << "Failed to write msg." << endl; return -1; } return 0; }
Msg1 是一个 helloworld 类的对象,set_id() 用来设置 id 的值。SerializeToOstream 将对象序列化后写入一个 fstream 流。
清单 3. Reader
#include "lm.helloworld.pb.h" … void ListMsg(const lm::helloworld & msg) { cout << msg.id() << endl; cout << msg.str() << endl; } int main(int argc, char* argv[]) { lm::helloworld msg1; { fstream input("./log", ios::in | ios::binary); if (!msg1.ParseFromIstream(&input)) { cerr << "Failed to parse address book." << endl; return -1; } } ListMsg(msg1); … }
同样,Reader 声明类 helloworld 的对象 msg1,然后利用 ParseFromIstream 从一个 fstream 流中读取信息并反序列化。此后,ListMsg 中采用 get 方法读取消息的内部信息,并进行打印输出操作。
运行结果
运行 Writer 和 Reader 的结果如下:
>writer >reader 101 Hello
Reader 读取文件 log 中的序列化信息并打印到屏幕上。
清单 4. 嵌套 Message 的例子
message Person { required string name = 1; required int32 id = 2; // Unique ID number for this person. optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; }
在 Message Person 中,定义了嵌套消息 PhoneNumber,并用来定义 Person 消息中的 phone 域。这使得人们可以定义更加复杂的数据结构。
Import Message
在一个 .proto 文件中,还可以用 Import 关键字引入在其他 .proto 文件中定义的消息,这可以称做 Import Message,或者 Dependency Message。
比如下例:
清单 5. 代码
import common.header; message youMsg{ required common.info_header header = 1; required string youPrivateData = 2; }
- Google Protocol Buffer的学习精要
- google的protocol buffer学习
- Google Protocol Buffer 学习
- Google Protocol Buffer 学习
- Google Protocol Buffer 学习
- Google Protocol Buffer学习笔记
- google的protocol buffer 分析
- google protocol buffer的使用
- google Protocol buffer(JAVA接口) 学习
- google Protocol buffer(JAVA接口) 学习
- Google的protocol buffer的实例
- FreeWheel的架构 -- Protocol Buffer by Google
- Google Protocol Buffer 的使用和原理
- Google Protocol Buffer 的使用和原理
- Google Protocol Buffer 的使用和原理
- Google Protocol Buffer 的使用和原理
- Google Protocol Buffer 的使用和原理
- Google Protocol Buffer 的使用和原理
- 借助net.sunniwell.core封装BaseManager&&EntityDao
- Android 图片压缩
- 数据库的分表分库
- 图像或优化有关的网站和博客
- C# 执行MD5算法报错
- Google Protocol Buffer的学习精要
- @Resource和@Autowired的区别
- 怎么利用xshell上传文件?
- [BZOJ2743][HEOI2012][树状数组]采花
- 解决 GlobalSign 证书导致 Mac 上京东、淘宝等网站打不开的问题
- android app运行显示两个图标
- Logstash过滤器--Geoip
- hdu 2767 Proving Equivalences(强连通分量+缩点)
- 欢迎使用CSDN-markdown编辑器