Protobuf入门

Protobuf是什么?

官网解释

Protobuf 是Google为序列化数据结构提供的语言无关,平台无关,可扩展的机制,它比XML更小更快更简单。你可以定义你想定义的数据表示成结构数据,然后你可以使用产生的代码去写或者从多种多样的数据流中读取你的结构数据,并且在多种多样的语言中使用。
Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.

下面我们编写一个例子,例子的目标是使用protobuf序列化和反序列化对象。在本例子中我们使用java编写,所以在这个过程用会引用到Maven构建项目。

例子

步骤一:编写proto文件

protobuf是一种跨语言的序列化/反序列化的工具,通过proto文件定义对象的数据结构,并依赖此proto文件进行序列化和反序列化操作。
新建PersonMsg.proto文件,详细定义如下:

//定义使用的protobuf版本
syntax = "proto3"; //(1)

//定义所在的protobuf包空间
package  com.simple;//(2)

//生成的java类所在的包路径
option java_package = "com.simple"; //(3)
//生成的java类的类名
option java_outer_classname = "PersonMsg"; //(4)

//声明一个message类
message Person{ //(5)
      string name = 1;  //(6)
      int32 age =2;//(7)
      string email =3;//(8)
      string phoneNumber =4;//(9)
}

简单解析一下:
(1)使用syntax关键字,定义要使用的protobuf版本,在这里我们使用proto3(注意:这个声明必须在第一行。)
(2)这个是用来防止不同protobuf message 类型的命名冲突,在不同语言中package对生成代码的影响也不一样,在java中,如果不显式提供option java_package参数,那么package所标明的内容就是生成java类所在的包路径。详细内容请查看原文下的package说明:protobuf guide
(3)~(4)标明java参数,其他语言不需要提供此参数。
如不提供java_package参数,会使用上面声明的package内容作为生成的java类的包路径。
如不提供java_outer_classname参数,会使用.proto文件的文件名作为生成java类的类名。
(5)这里声明了一个名字是Person的message(注意:这里message的名字不能跟上面 java_outer_classname参数定义的名字一样。)
(6)~(9)在这里声明了4个字段,声明字段的格式是 "类型 字段名=标号",在protobuf中,提供丰富的字段类型,在官网guide中可以查看proto类型对应产生不同语言的类型(详细查看Guide中的Scalar Value Types:protobuf guide)。message的标号都是从1开始递增,标号是不允许重复的。

步骤二:下载protobuf的编译工具

编写完proto文件,我们需要一个工具去编译它,所以我们需要下载protoc.exe。
下载方式:在官网中下载protoc-3.4.0-win32.zip(下载地址:protobuf 3.4下载链接),解压可以看到在bin目录下的protoc.exe,如下图:

解压后protoc.exe路径

protoc.exe是使用c++编写的proto文件的编译工具,文章后面我们会介绍使用protoc.exe编译proto文件产生对应的java类。

步骤三:新建Maven工程

在这个演示的案例中,我们使用maven构建项目。然后在src/main下新增protos目录存放.proto文件。
项目的目录结构如下:


项目结构

因为我们这里使用的是java,所以要引入protobuf-java.jar来操作protobuf。我们使用的maven,所以直接在pom.xml中加入protobuf-java.jar的依赖。完整的pom.xml如下图:

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.protobuf</groupId>
  <artifactId>myprotobuflearn</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>myprotobuflearn</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.10</version>
          <scope>test</scope>
        </dependency>
        
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.4.0</version>
        </dependency>
      </dependencies>
</project>

步骤四:编译proto文件

这一步我们需要使用下载的protoc.exe文件编译proto文件,产生对应的java类。
首先,把protoc.exe拷贝到工程src/main/protos目录下
然后,把步骤一所编写的proto文件也拷贝到src/main/protos目录下
进入cmd命令行,进入protoc.exe所在路径,输入如下命令:

protoc --java_out=../java PersonMsg.proto

因为我执行此命令时,protoc.exe和PersonMsg.proto在同一目录下,所以不用指定proto_path参数(默认会扫描protoc.exe所在目录的proto文件)。在这里指定生成java类所在目录为protos同级目录java文件夹下。
完整的命令格式:

protoc.exe --proto_path=$PROTO_DIR --java_out=$JAVA_OUT_DIR  xxx.proto

说明:
1.proto_path是要编译的proto文件所在文件夹路径,protoc.exe会扫描这个路径,找到后面要求编译的proto文件
2.java_out是编译生成的java类存放的路径
3.最后就是要编译的proto文件的路径

执行编译命令后,我们去到src/main/java目录下查看是否有java类生成。


PersonMsg.java

步骤四:编写测试类

上面我们已经成功编译protoc文件生成了对应Java类,现在我们就可以编写一个测试类验证一下protobuf的序列化和反序列化。
回到我们maven工程,在src/main/test中新增测试类PersonTest.java,代码如下:

package com.simple;

import static org.junit.Assert.*;

import java.io.IOException;
import org.junit.Test;
import com.simple.PersonMsg.Person;

public class PersonMsgTest {

    
    @Test
    public void testSerilize() throws IOException{
        Person.Builder personBuilder = Person.newBuilder();//(1)
        
        personBuilder.setName("changzhang");
        personBuilder.setAge(18);
        personBuilder.setEmail("123456789@qq.com");
        personBuilder.setPhoneNumber("98765432");
        
        Person orginPerson = personBuilder.build();//(2)
        
        //序列化originPerson对象,转换成byte数组
        byte[] byteArray = orginPerson.toByteArray();//(3)
        
        
        //反序列化
        Person newPerson = Person.parseFrom(byteArray);//(4)
        
        assertEquals(newPerson.getName(),orginPerson.getName());
        assertEquals(newPerson.getAge(), orginPerson.getAge());
        assertEquals(newPerson.getEmail(), orginPerson.getEmail());
        assertEquals(newPerson.getPhoneNumber(), orginPerson.getPhoneNumber());
    }
}

说明:
(1)在protobuf中使用builder模式构造序列化对象。
(2)调用build方法构造对象,对象已经构造就不能改变。
(3) 使用toByteArray方法,把originPerson序列化成byte数组
(4)使用parseFrom方法反序列化,传入刚刚的byte数组
序列化和反序列化说明,请参考官网guide->Tutorials->java里面的Parsing and Serialization内容(连接

运行下junit,ok!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容

  • 由于工程项目中拟采用一种简便高效的数据交换格式,百度了一下发现除了采用 xml、JSON 还有 ProtoBuf(...
    黄海佳阅读 48,020评论 1 23
  • Protobuf全称Protocol Buffers,简称GPB、PB,是QQ等IM采用的协议,比XML、XMPP...
    NinaX阅读 6,275评论 0 2
  • 1 Introduction Protocol Buffers是在网络通讯或者数据存储时用到的一种语言无关、平台无...
    天才木木阅读 3,092评论 22 9
  • 0.前言 上一章主要写了一些基础语法,命名规范等,但是只有这些明显是不够的,也无法实现我们自己想要的结果,今天来主...
    紫荆峰阅读 332评论 0 1
  • 人生的最大悲剧是:自由也许可能得到,而我们却经年累月将自己限于同样的模式中。----Bryan Johnson 最...
    紫苑阅读 431评论 3 5