ProtoBuf的隨筆

1、為什么使用Protocal Buffers

通常序列化和解析結(jié)構(gòu)化數(shù)據(jù)的幾種方式?
1、使用Java默認(rèn)的序列化機(jī)制。這種方式缺點(diǎn)很明顯:性能差、跨語(yǔ)言性差。
2、將數(shù)據(jù)編碼成自己定義的字符串格式。簡(jiǎn)單高效,但是僅適合比較簡(jiǎn)單的數(shù)據(jù)格式。
3、使用XML序列化。比較普遍的做法,優(yōu)點(diǎn)很明顯,人類(lèi)可讀,擴(kuò)展性強(qiáng),自描述。但是相對(duì)來(lái)說(shuō)XML結(jié)構(gòu)比較冗余,解析起來(lái)比較復(fù)雜性能不高。

2、protoBuf的語(yǔ)法:

.proto文件的語(yǔ)法跟java的很相似,message相當(dāng)于class, enum和java中的枚舉還是同一個(gè)玩意,基本數(shù)據(jù)類(lèi)型有bool,int32, float,double和string

類(lèi)型前的修飾符有:

1、required 必須的字段
2、optional 可選的字段
3、repeated 重復(fù)的字段

由于歷史原因,數(shù)值型的repeated字段后面最好加上[packed=true],這樣能達(dá)到更好的編碼效果。 repeated int32 samples = 4 [packed=true];

proto2不支持map,需要的話(huà)只能用兩個(gè)repeated代替key和value,proto3支持了map

擴(kuò)展:

1、Extensions保留一些field number讓第三方去擴(kuò)展
message Foo{
          required int32 a = 1;
extensions 100 to 199;  
}
message Bar {

    optional string name =1;
    optional Foo foo = 2;
} 

extend Foo {
    optional int32 bar = 102;
}
message Bar {

    optional string name =1;
    optional Foo foo = 2;
} 

extend Foo {
    optional int32 bar = 102;
}

嵌套:

message Bar {

    extend Foo {
    optional int32 bar = 102;
    }

    optional string name =1;
    optional Foo foo = 2;
}

2、編譯proto文件

在windows下需要用protoc.exe編譯成java文件(http://download.csdn.net/download/zhshchilss/8470577)下載解壓后。

1、在文件夾下編寫(xiě)一個(gè)proto文件,我這里用Msg.proto
package protobuf;   
option java_package = "com.example";     //包名
option java_outer_classname = "FirstProtobuf";   //類(lèi)名  
message testBuf  {   
  required int32 ID = 1;   
  optional string Url = 2;   
  repeated string name=3;   
    
   enum PhoneType {   
    MOBILE = 0;   
    HOME = 1;   
    WORK = 2;   
  }  
} 
2、按住shift+鼠標(biāo)右鍵,彈出在此處打開(kāi)命令行窗口,然后輸入命令:protoc ./Msg.proto --java_out=./ 回車(chē)。然后在文件夾下就可以看到生成的文件。

#######2.1或者是將命令寫(xiě)入到run_java.bat腳本中,直接運(yùn)行腳本,就會(huì)幫你生成。

3、開(kāi)始測(cè)試:

可以用AS或者是Eclipse都行,將上面的文件夾下的

1、首先把上面的protobuf-java-2.4.1.jar放到工程的lib目錄下,build path就OK
2、把剛才生成的proto文件放到目錄下,記得這個(gè)目錄一定要是和proto內(nèi)部的目錄是一樣的,否則會(huì)報(bào)錯(cuò)。
3、開(kāi)始寫(xiě)代碼。
package com.example;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.google.protobuf.InvalidProtocolBufferException;

public class MyTest {

    public static void main(String[] args) {
        
        byte[] result = serializable();
        getData(result);
    }

    private static byte[] serializable() {
        FirstProtobuf.testBuf.Builder build = FirstProtobuf.testBuf.newBuilder();
        build.setID(777);
        List<String> values = new ArrayList<String>();
        values.add("aaa");
        values.add("aba");
        values.add("baa");
        values.add("acc");
        build.addAllName(values);
        
        FirstProtobuf.testBuf info = build.build();
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        try {
            info.writeTo(output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //序列化成字節(jié)數(shù)組
        byte[] result = info.toByteArray();
        
        System.out.println(result.toString());
        System.out.println("=================================");
        return result;
    }

    private static void getData(byte[] result) {
        try {
            //反序列化
            ByteArrayInputStream input = new ByteArrayInputStream(result);
            FirstProtobuf.testBuf testbuf = FirstProtobuf.testBuf.parseFrom(input);
            System.out.println(testbuf);
            System.out.println(FirstProtobuf.testBuf.PhoneType.HOME);
        } catch (InvalidProtocolBufferException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

以上就是protobuf的簡(jiǎn)單基礎(chǔ)使用方法,謝謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容