Protobuf入門

Protobuf是什么?

官網(wǎng)解釋

Protobuf 是Google為序列化數(shù)據(jù)結(jié)構(gòu)提供的語言無關,平臺無關,可擴展的機制,它比XML更小更快更簡單。你可以定義你想定義的數(shù)據(jù)表示成結(jié)構(gòu)數(shù)據(jù),然后你可以使用產(chǎn)生的代碼去寫或者從多種多樣的數(shù)據(jù)流中讀取你的結(jié)構(gòu)數(shù)據(jù),并且在多種多樣的語言中使用。
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構(gòu)建項目。

例子

步驟一:編寫proto文件

protobuf是一種跨語言的序列化/反序列化的工具,通過proto文件定義對象的數(shù)據(jù)結(jié)構(gòu),并依賴此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參數(shù),那么package所標明的內(nèi)容就是生成java類所在的包路徑。詳細內(nèi)容請查看原文下的package說明:protobuf guide
(3)~(4)標明java參數(shù),其他語言不需要提供此參數(shù)。
如不提供java_package參數(shù),會使用上面聲明的package內(nèi)容作為生成的java類的包路徑。
如不提供java_outer_classname參數(shù),會使用.proto文件的文件名作為生成java類的類名。
(5)這里聲明了一個名字是Person的message(注意:這里message的名字不能跟上面 java_outer_classname參數(shù)定義的名字一樣。)
(6)~(9)在這里聲明了4個字段,聲明字段的格式是 "類型 字段名=標號",在protobuf中,提供豐富的字段類型,在官網(wǎng)guide中可以查看proto類型對應產(chǎn)生不同語言的類型(詳細查看Guide中的Scalar Value Types:protobuf guide)。message的標號都是從1開始遞增,標號是不允許重復的。

步驟二:下載protobuf的編譯工具

編寫完proto文件,我們需要一個工具去編譯它,所以我們需要下載protoc.exe。
下載方式:在官網(wǎng)中下載protoc-3.4.0-win32.zip(下載地址:protobuf 3.4下載鏈接),解壓可以看到在bin目錄下的protoc.exe,如下圖:

解壓后protoc.exe路徑

protoc.exe是使用c++編寫的proto文件的編譯工具,文章后面我們會介紹使用protoc.exe編譯proto文件產(chǎn)生對應的java類。

步驟三:新建Maven工程

在這個演示的案例中,我們使用maven構(gòu)建項目。然后在src/main下新增protos目錄存放.proto文件。
項目的目錄結(jié)構(gòu)如下:


項目結(jié)構(gòu)

因為我們這里使用的是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文件,產(chǎn)生對應的java類。
首先,把protoc.exe拷貝到工程src/main/protos目錄下
然后,把步驟一所編寫的proto文件也拷貝到src/main/protos目錄下
進入cmd命令行,進入protoc.exe所在路徑,輸入如下命令:

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

因為我執(zhí)行此命令時,protoc.exe和PersonMsg.proto在同一目錄下,所以不用指定proto_path參數(shù)(默認會掃描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文件的路徑

執(zhí)行編譯命令后,我們?nèi)サ絪rc/main/java目錄下查看是否有java類生成。


PersonMsg.java

步驟四:編寫測試類

上面我們已經(jīng)成功編譯protoc文件生成了對應Java類,現(xiàn)在我們就可以編寫一個測試類驗證一下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對象,轉(zhuǎn)換成byte數(shù)組
        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模式構(gòu)造序列化對象。
(2)調(diào)用build方法構(gòu)造對象,對象已經(jīng)構(gòu)造就不能改變。
(3) 使用toByteArray方法,把originPerson序列化成byte數(shù)組
(4)使用parseFrom方法反序列化,傳入剛剛的byte數(shù)組
序列化和反序列化說明,請參考官網(wǎng)guide->Tutorials->java里面的Parsing and Serialization內(nèi)容(連接

運行下junit,ok!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 由于工程項目中擬采用一種簡便高效的數(shù)據(jù)交換格式,百度了一下發(fā)現(xiàn)除了采用 xml、JSON 還有 ProtoBuf(...
    黃海佳閱讀 49,145評論 1 23
  • Protobuf全稱Protocol Buffers,簡稱GPB、PB,是QQ等IM采用的協(xié)議,比XML、XMPP...
    NinaX閱讀 6,431評論 0 2
  • 1 Introduction Protocol Buffers是在網(wǎng)絡通訊或者數(shù)據(jù)存儲時用到的一種語言無關、平臺無...
    天才木木閱讀 3,242評論 22 9
  • 0.前言 上一章主要寫了一些基礎語法,命名規(guī)范等,但是只有這些明顯是不夠的,也無法實現(xiàn)我們自己想要的結(jié)果,今天來主...
    紫荊峰閱讀 398評論 0 1
  • 人生的最大悲劇是:自由也許可能得到,而我們卻經(jīng)年累月將自己限于同樣的模式中。----Bryan Johnson 最...
    紫苑閱讀 522評論 3 5

友情鏈接更多精彩內(nèi)容