簡(jiǎn)介
protocolbuffer(以下簡(jiǎn)稱protobuf)是google 的是一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,作用形同于xml和json凫岖。它獨(dú)立于語(yǔ)言,獨(dú)立于平臺(tái)。google 提供了多種語(yǔ)言的實(shí)現(xiàn):java库车、c#、c++樱拴、go 和 python柠衍,每一種實(shí)現(xiàn)都包含了相應(yīng)語(yǔ)言的編譯器以及庫(kù)文件。由于它是一種二進(jìn)制的格式晶乔,比使用 xml 進(jìn)行數(shù)據(jù)交換快許多珍坊。可以把它用于分布式應(yīng)用之間的數(shù)據(jù)通信或者異構(gòu)環(huán)境下的數(shù)據(jù)交換正罢。作為一種效率和兼容性都很優(yōu)秀的二進(jìn)制數(shù)據(jù)傳輸格式阵漏,可以用于諸如網(wǎng)絡(luò)傳輸、配置文件、數(shù)據(jù)存儲(chǔ)等諸多領(lǐng)域履怯。
protobuf優(yōu)點(diǎn)
Protobuf 有如 XML回还,不過(guò)它更小、更快叹洲、也更簡(jiǎn)單柠硕。你可以定義自己的數(shù)據(jù)結(jié)構(gòu),然后使用代碼生成器生成的代碼來(lái)讀寫這個(gè)數(shù)據(jù)結(jié)構(gòu)疹味。你甚至可以在無(wú)需重新部署程序的情況下更新數(shù)據(jù)結(jié)構(gòu)仅叫。只需使用 Protobuf 對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行一次描述,即可利用各種不同語(yǔ)言或從各種不同數(shù)據(jù)流中對(duì)你的結(jié)構(gòu)化數(shù)據(jù)輕松讀寫糙捺。
它有一個(gè)非常棒的特性诫咱,即“向后”兼容性好,人們不必破壞已部署的洪灯、依靠“老”數(shù)據(jù)格式的程序就可以對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行升級(jí)坎缭。這樣您的程序就可以不必?fù)?dān)心因?yàn)橄⒔Y(jié)構(gòu)的改變而造成的大規(guī)模的代碼重構(gòu)或者遷移的問(wèn)題。因?yàn)樘砑有碌南⒅械?field 并不會(huì)引起已經(jīng)發(fā)布的程序的任何改變签钩。
Protobuf 語(yǔ)義更清晰掏呼,無(wú)需類似 XML 解析器的東西(因?yàn)?Protobuf 編譯器會(huì)將 .proto 文件編譯生成對(duì)應(yīng)的數(shù)據(jù)訪問(wèn)類以對(duì) Protobuf 數(shù)據(jù)進(jìn)行序列化、反序列化操作)铅檩。
使用 Protobuf 無(wú)需學(xué)習(xí)復(fù)雜的文檔對(duì)象模型憎夷,Protobuf 的編程模式比較友好,簡(jiǎn)單易學(xué)昧旨,同時(shí)它擁有良好的文檔和示例拾给,對(duì)于喜歡簡(jiǎn)單事物的人們而言,Protobuf 比其他的技術(shù)更加有吸引力兔沃。
protobuf不足
Protbuf 與 XML 相比也有不足之處蒋得。它功能簡(jiǎn)單,無(wú)法用來(lái)表示復(fù)雜的概念乒疏。
XML 已經(jīng)成為多種行業(yè)標(biāo)準(zhǔn)的編寫工具额衙,Protobuf 只是 Google 公司內(nèi)部使用的工具,在通用性上還差很多怕吴。
由于文本并不適合用來(lái)描述數(shù)據(jù)結(jié)構(gòu)窍侧,所以 Protobuf 也不適合用來(lái)對(duì)基于文本的標(biāo)記文檔(如 HTML)建模。另外转绷,由于 XML 具有某種程度上的自解釋性伟件,它可以被人直接讀取編輯,在這一點(diǎn)上 Protobuf 不行暇咆,它以二進(jìn)制的方式存儲(chǔ)锋爪,除非你有 .proto 定義,否則你沒(méi)法直接讀出 Protobuf 的任何內(nèi)容爸业。
使用流程
1.編寫protobuf文件
package jjd;
option java_package = "Lt.messagePush.vo.hardware.req";
option java_outer_classname = "HwWifiToAppReqProto";
message HwWifiToAppReq{
required string serialNum=1;
required int64 userId = 2;
required string account=3;
required string password=4;
optional bool has4G=5;
optional bool is4G=6;
}
2.編譯protobuf文件
利用wire-compiler-2.0.1-jar-with-dependencies.jar包可以直接編譯protobuf文件
1.打開(kāi)cmd進(jìn)入jar包目錄
2.輸入:
java -jar -Dfile.encoding=UTF-8 wire-compiler-2.0.1-jar-with-dependencies.jar --proto_path=F:\protobuf --java_out=F:\protobuf ActivityDetailReq.proto
-Dfile.encoding=UTF-8 : 指明生成的java文件編碼是utf8其骄,不指明的話,會(huì)使用系統(tǒng)編碼扯旷。在win7系統(tǒng)默認(rèn)gbk拯爽,會(huì)出現(xiàn)中文亂碼。
--proto_path:proto文件路徑
--java_out : java文件的生成目錄钧忽。在此目錄中根據(jù)protobuf中定義的包名來(lái)生成對(duì)應(yīng)的包結(jié)構(gòu)
3.Android中使用protobuf傳輸
HwWifiToAppReq.Builder builder = new HwWifiToAppReq.Builder();
builder.serialNum(serialNum)
.userId(userId)
.account(wifiInfo.getSSID().replace("\"",""))
.password("")
.has4G(NetUtil.isSimReady(AppApplication.context))
.is4G(NetUtil.isMobileNet(AppApplication.context));
SocketManager.getInstance(context).sendRequest(MessageType.HARDWARE_WIFI_TO_APP, builder.build().toByteArray(), new OnMinaCallBackInterface() {
@Override
public void loading() {
}
@Override
public void success(MsgCmdVo msg) {
}
@Override
public void failed(int respCode) {
SocketManager.onLogin = false;
logInInterface.failed(respCode);
}
});
4.Android中解析protobuf
在我們的項(xiàng)目中是使用com.squareup.wire:wire-runtime:1.7.0來(lái)解析protobuf文件
import com.squareup.wire.Wire;
Wire wire = new Wire();
//vo.getMsg()是從云端下發(fā)的protobuf
HwGetWifiPush hwGetWifiPush = wire.parseFrom(vo.getMsg(), HwGetWifiPush.class)毯炮;
loginPresenter.sendWifiInfoToApp(DEVICE_ID, hwGetWifiPush.userId);