Protocol Buffer序列化/反序列化---初體驗(java版)


今天閑遐時學習了

Protocol Buffer

在網上看到了許多資料,其中不泛精品,想要詳細了解的請看文章結尾的友情鏈接,我這里就做加深印象,快速入門的一個完整的demo,僅此而已.

學完你可以得到什么:

  1. 可以使用protoc工具序列化類,反序列化類
  2. 基於java語言的對protoc工具的基本使用
  3. 基本protoc的基礎api使用

首先我們需要下載官方的編譯工具,

翻牆版: 官方文檔

不翻版:我的倉庫

整體流程:序列化一個實體類,在反序列出來得到結果:

先放出結果來瞅瞅:

可以看到數據壓縮了將近一半多,so GOOD!!!

言歸正傳:

首先我們

 新建一個proto文件,定義基本的數據格式

 

syntax = "proto2";

option java_outer_classname="PersonProtoBuf";

message Person{
	optional int32 id = 1;
	optional int32 age = 2;
	optional string name= 3;
	optional  bool is_sex= 4;
}
message Class{
	optional int32 grade_num = 1;
	optional int32 class_num = 2;
	optional Person head_teacher = 3;	
	repeated Person students = 4[packed=true];
}
* 第一句確定是語法版本
* 其二是指定生成的class
* 還可以指定包名
* 主體:
*  message Person{...}
*  主要實體編寫區域
*  其中:
*      optional:非必需參數
*      repeated:可以重復存儲一個字段,其中是待順序的存取
*      required:必要參數
*
*      結構體、類,統一定義為 message,實際上是嵌套類
*
*      int32,string,bool 數據格式
*      1,2,3,4 表示數據元素的唯一編號
*
*
* 還可以定義:
*  enum xx          //枚舉定義
*     {
*         XXX = 0;
*         ...
*     }
*
*  struct SS{           //結構體定義
*         required int s1;
*         required int s2;
*     }
*
* 具體需要翻牆查看官網文檔: https://developers.google.com/protocol-buffers/docs/javatutorial
* 接下來就需要:使用java程序進行壓縮,模擬解壓.
這個protoc的工具加不加環境變量隨便,使用命令(我這里是加了環境變量):
protoc --java_out=./ ./****.proto文件
其中第一個./是將生成的java文件放在本目錄下,其二個則是在找到這個proto文件,
這里還需要編寫其proto文件...

 執行結果:

我們現在創建java項目,添加protocol 的jar依賴

        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.7.0-rc1</version>
        </dependency>

  基本結構

public class ServiceSchool {


    private PClass pClass = null;

    /**
     * 初始化班級
     */
    @Before
    public void initClass(){
        //設置教師類
        Person teacher = new Teacher(1,30,"王老師",false);

        //設置學生類 一個班級50人
        List<Person> allStudents = new ArrayList<>();
        for(int i = 0; i < 50; i++) {
            Person student = null;
            if(i % 2 == 0) {
                student = new Student(i + 1000, (int) (Math.random() * 20), "學生" + i + "號", true);
            }else{
                student = new Student(i + 1000, (int) (Math.random() * 20), "學生" + i + "號", false);
            }
            allStudents.add(student);
        }
        pClass = new PClass(7,3,teacher,allStudents);
    }

    /**
     * 模擬傳輸的數據字節數組
     */
    private byte[] pipeByArray = null;

    /**
     * 壓縮
     */
    @Test
    public void compression() throws InvalidProtocolBufferException {
//        原數據
        System.out.println("原數據的長度: "+pClass.toString().length());
        //壓縮后
        School.Class.Builder pClassCom = setBuilder(pClass);
        School.Class build = pClassCom.build();
        pipeByArray = build.toByteArray();
        System.out.println("壓縮后數據長度:"+pipeByArray.length);
    }

    /**
     * 模擬解壓
     */
    @After
    public void decompression() throws InvalidProtocolBufferException {
        School.Class.Builder aClass = School.Class.parseFrom(pipeByArray).toBuilder();
////        解壓
        int classNum = aClass.getClassNum();
        int gradeNum = aClass.getGradeNum();
        School.Person headTeacher = aClass.getHeadTeacher();
        List<School.Person> studentsList = aClass.getStudentsList();
        System.out.println("教師:"+headTeacher.getId()
                +headTeacher.getName()
                +headTeacher.getAge()
                +headTeacher.getIsSex());
        for(School.Person p : studentsList){
            System.out.println(p.getName()+"-"+p.getId()+"-"+p.getIsSex()+"-"+p.getAge());
        }
    }

    /**
     * 添加數據
     *
     * @param pClass
     * @return
     */
    private School.Class.Builder setBuilder(PClass pClass){
        School.Person.Builder person = School.Person.newBuilder();
        //教師類
        Person headTeacher = pClass.getHeadTeacher();
        //添加教師類
        person.setName(headTeacher.getName());
        person.setAge(headTeacher.getAge());
        person.setIsSex(headTeacher.isSex());
        person.setId(headTeacher.getId());
        //教室類
        School.Class.Builder sClass = School.Class.newBuilder();
        sClass.setGradeNum(pClass.getGradeNum());
        sClass.setClassNum(pClass.getClassNum());
        sClass.setHeadTeacher(person);

        //遍歷學生
        for(int i = 0; i < pClass.getStudents().size();i++){
            Person p = pClass.getStudents().get(i);
            person.setName(p.getName());
            person.setAge(p.getAge());
            person.setIsSex(p.isSex());
            person.setId(p.getId());
            sClass.addStudents(i,person);
        }

        return sClass;
    }
}

  

發現其中數據量越少,壓縮后會更小基本上都是1/3原來的體積,下一次准備使用這個協議做rpc了,哈哈

參考網站:

https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
https://worktile.com/tech/share/prototol-buffers


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM