微信扫一扫

028-83195727 , 15928970361
business@forhy.com

【Google Protobuf】windows下protobuf的开发环境搭建和使用

protobuf,protobuf java2016-07-20

Protobuf介绍

 Protobuf是由谷歌开源而来,在谷歌内部久经考验。它将数据结构以.proto文件进行描述,通过代码生成工具可以生成对应数据结构的POJO对象和Protobuf相关的方法和属性。

特点如下:

  • 结构化数据存储格式(XML,JSON等)
  • 高效的编解码性能
  • 语言无关、平台无关、扩展性好
  • 官方支持Jaca、C++、Python三种语言

序列化数据对比


bytes字节数对比


以上是摘自http://blog.163.com/jekyll_zhou@126/blog/static/18204738201210303283975/的测试结果

准备

限定修饰符

  • required: 表示是一个必须字段,发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。
  • Optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。
  • Repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。

基本类型

  • bool: 布尔类型 1字节
  • int32: 32位有符号整数
  • uin32: 32位无符号整数
  • int64: 64位有符号整数
  • uin64:64位无符号整数
  • sint32:32位整数,处理负数效率更高
  • sint64:64位整数,处理负数效率更高
  • double: 64位浮点数
  • string: 只能处理ASCII字符
  • bytes:用于处理多字节的语言字符、如中午

关于 fixed32 和int32的区别。fixed32的打包效率比int32的效率高,但是使用的空间一般比int32多。因此一个属于时间效率高,一个属于空间效率高。根据项目的实际情况,一般选择fixed32,如果遇到对传输数据量要求比较苛刻的环境,可以选择int32.

枚举(enum)

枚举的定义形式和Java的Enum定义差不多,例如:

  enum PhoneType {
        MOBILE=0;
        HOME=1;
        WORK=2;
    }

结构体(message)

message,类似于C语言中的结构体。例如:

message Login
{
	optional string username = 1;
	optional string password = 2;
}

字段名称

字段名称的命名与C、C++、Java等语言的变量命名方式几乎是相同的。
protobuf建议字段的命名采用以下划线分割的驼峰式。例如 first_name 而不是firstName.


字段编码值

1900~2000编码值为Google protobuf 系统内部保留值,建议不要在自己的项目中使用。


protobuf java的使用

1.创建一个新的工程Protobuf,将protoc.exe文件拷贝到当前目录


2.在protoc.exe同级目录创建helloworld.proto文件,代码如下

message Person {
  
  // ID(必需)
  required int32 id = 1;
  
  // 姓名(必需)
  required string name = 2;
  
  // email(可选)
  optional string email = 3;

  // 朋友(集合)
  repeated string friends = 4;
}

3.使用如下命令编译这个helloworld.proto文件

protoc.exe --java_out=./ helloworld.proto


4.编译后在当前目录多出来一个Helloworld.java文件


5.把Helloworld.java文件和protobuf-java-2.6.1.jar引入到eclipse项目


6.序列化代码

Helloworld.Person.Builder builder = Helloworld.Person.newBuilder();
builder.setId(1);
builder.setName("小毛驴");
builder.setEmail("1805348347@qq.com");
		
Helloworld.Person person = builder.build();
byte[] result = person.toByteArray();

7.反序列化代码

	   try {
			Helloworld.Person person1 = Helloworld.Person.parseFrom(result);
			System.out.println(person1);
		} catch (InvalidProtocolBufferException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


8.运行结果

id: 1
name: "\345\260\217\346\257\233\351\251\264"
email: "1805348347@qq.com"