Protobuf笔记

来源:互联网 发布:大疆精灵4pos数据导出 编辑:程序博客网 时间:2024/05/23 13:21

《Protobuf笔记》

转载自:http://blog.itpub.net/23937368/viewspace-1057905/

Google Protocol Buffer 是一个平台无关、语言无关的结构化数据的序列化与反序列化工具。

使用方式:
1) define proto files AddressBook.proto
2) Invoke protoc to build AddressBookProtos.java:
$ protoc --java_out=src/main/java -I../src 
../src/google/protobuf/AddressBook.proto
eg. protoc --proto_path=. --java_out=. mytest/AddressBook.proto
3) Compile the code in src/main/java using whatever means you prefer.
4) Install the classes wherever you prefer.


proto文件demo:
==================================================
package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

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;
}

// Our address book file is just one of these.
message AddressBook {
repeated Person person = 1;
}
==================================================

语法解释:
在.proto文件中,最基本的数据类型为message,其定义如上所示,由message引导,之后是message类型的名字,之后是由{}包含的各个域(fields)。

required string name = 1; 域字义的一个例子。
required 表示这个域是必需的
optional 该域选,出现0次或1次
repeated 重复出现,0次或多次

string是域的类型,可是简单的标量类型(如bool,int32,float,double,string等),也可是复合类型(message,enum等)

name是域的名字,=1是给域一个数字标签,这会影响到该域在二进制文件中顺序。
关于这个数字标签也是有说明的,1到15是只使用一个字节编号,而其他的使用多个字节,所以应把1-15编号给最经常使用的域。数字标签的最大值为2**29 - 1(或536,870,911),其中还有一段是保留用于proto的实现,从19000到19999 (FieldDescriptor::kFirstReservedNumber 到FieldDescriptor::kLastReservedNumber)。

有optional说明的域可以有一个默认值,在不指定该域时使用,如optional PhoneType type = 2 [default = HOME];

还有一种类型是enum,如上enum PhoneType的定义。类型可以定义一在一个message类型中,也可以单独定义,如上enum PhoneType和message PhoneNumber是嵌套定义在message Person中,message AddressBook中单独定义的。  

可以访问一个嵌套定义在另一个message类型中的message,但需使用域范围标示,如同的c++里使用另一个命名空间的类:person::PhoneNumber。

添加注释://

  optional int32 page_number = 2;// Which page number do we want?

导入:proto可以导入在不同的文件中的定义。通过在文件顶端加入一个import语句

  import "myproject/other_protos.proto";

扩展:proto支持将一定范围内的数字编号作为扩展时使用。对扩展的使用也需使用范围方法。

  message Foo {
   // ...
  extensions 100 to 199;
  }


  extend Foo {
   optional int32 bar = 126;
  }

包:proto支持包的使用,以防止命名冲突。在文件的开始部分指定:package tutorial。不同的语言在生成代码对包的处理是不同的:c++中作为命名空间,java中也作包,python中是模块。

Options:可使用option来指定一些选项,会对生成的代码有一些影响。option分文件层的和域层的。在上面的例子中就使用了文件层的:

  option java_package = "com.example.tutorial";
  option java_outer_classname = "AddressBookProtos";

生成代码:使用proto编译器就可以生成相应语言的代码。

protoc --proto_path=IMPORT_PATH --cpp_out=DST_DIR --java_out=DST_DIR --python_out=DST_DIR  path/file.proto
 protoc.exe是编译器的名字;--proto_path指定对导入文件的搜索路径,若不指定,则为当前路径;--cpp_out指定生成c++文件的路径,--java_out和 --python_out分别是生成java和python代码的路径;path/file.proto是定义结构的.proto文件。

使用c++语言,会生成针对每个message类型的一个类,对每一个类也提供了相应的处理方法,还提供了序列化到输出流和从输入流中解析的方法。


相关资源:protobuf 组件包
protobuf-java-2.4.1.jar
http://www.java2s.com/Code/JarDownload/protobuf/protobuf-java-2.4.1.jar.zip

google ProtoBuf开发者指南

http://www.cnblogs.com/foxhengxing/archive/2010/08/10/1796165.html

google protobuf doc

https://developers.google.com/protocol-buffers/docs/javatutorial?hl=zh-CN

[@more@]

0 0