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ǔ)使用方法,謝謝