還在用json喂窟?讓ProtocolBuffer為你的數(shù)據(jù)瘦瘦身

前言

protobuf是什么的测暗?

Protocol Buffer是一種用于序列化數(shù)據(jù)的協(xié)議央串。可以用來通信傳輸碗啄,數(shù)據(jù)傳輸?shù)戎屎汀?梢杂脕砣〈鷍son稚字,xml等饲宿。

為什么要用protobuf?

解析速度快胆描,生成的消息體積小瘫想,語法簡潔明了,支持多種語言( C++袄友、C#殿托、Go、Java剧蚣、Python支竹、JavaScript等等)

正如下圖,protobuf會把數(shù)據(jù)的體積壓縮到盡可能的小鸠按。


圖片來源:https://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html
圖片來源:https://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html
官方的api

protobuf由谷歌開發(fā)礼搁,谷歌內(nèi)部都在使用,所以放心地使用吧目尖。 這是github上的地址 https://github.com/google/protobuf

前期準備

1馒吴,安裝maven庫

官網(wǎng)下載對應(yīng)的maven。
下載后是一個壓縮包瑟曲,解壓饮戳。然后對應(yīng)的bin目錄(比如 C:\Program Files\apache-maven-3.3.9\bin)配置到環(huán)境變量PATH中就好了。

配置好環(huán)境變量之后洞拨,到命令行中扯罐,輸入

mvn -v

會看到類似這樣的輸出,就證明你的maven已經(jīng)配置成功了烦衣。

Apache Maven 3.3.3 (7994120775791599e205a5524ec3e0dfe41d4a06; 2015-04-22T04:57:37-07:00)
Maven home: /opt/apache-maven-3.3.3
Java version: 1.8.0_45, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "mac os x", version: "10.8.5", arch: "x86_64", family: "mac"

2歹河, 配置protoc的環(huán)境變量

  1. 從這個地址下載protoc-3.2.0-win32.zip文件。
  2. 解壓花吟。
  3. 把里面的protoc.exe配置到環(huán)境變量中去秸歧。

3,生成jar包

  1. 我們需要生成jar包衅澈,放到Android項目的lib中键菱,項目才能使用protobuf。
    同樣也是這個地址矾麻。這次需要下載protobuf-java-3.2.0.zip纱耻。如果你使用的是其他語言芭梯,就下載不同語言對應(yīng)的文件即可险耀。

注意:步驟2和步驟3中用到的包的版本號要一致弄喘。

  1. 解壓protobuf-java-3.2.0.zip。
  2. 把步驟2中得到的protoc.ext放到protobuf-java-3.2.0/src中
  3. 用命令行甩牺,cd到protobuf-java-3.2.0/java目錄下
  4. 輸入指令

mvn test

  1. 繼續(xù)輸入指令

mvn package

運行成功后蘑志,jar包就會出現(xiàn)在protobuf-java-3.2.0/java/core/target目錄下了。

編寫proto文件

這是一個簡單的proto文件贬派。

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}
  • 語法是不是很簡單
  • syntax = "proto3";表示語言的版本為proto3急但,如果不定義,系統(tǒng)就默認為proto2
  • SearchRequest定義了一個信息搞乏。里面存放著三個變量波桩。一個string類型,兩個int類型请敦。
  • 可以看到镐躲,三個變量后面分別跟著1,2,3。這不是變量的值侍筛,這是一個tag萤皂,標(biāo)志這個標(biāo)量在二進制格式里的位置。因為1-15只需要一個byte匣椰,而16到2047需要兩個byte裆熙,所以我們需要把常用的變量放到1-15中去。而tag的值可以從1定義到536,870,911禽笑,除了19000到19999入录。
  • 具體的所有數(shù)據(jù)類型,可以到官網(wǎng)看佳镜。

加上稍微復(fù)雜一點的proto文件

syntax = "proto3";

message SearchRequest {
//這是一個枚舉
enum Type{
  FAST_SEARCH = 0;
  SLOW_SEARCH = 1;
  NOTHING = 3;
}
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
  Type type = 4;//上面定義的枚舉僚稿,這里就可以用了
  bytes data = 5;//這是一個bytes類型的數(shù)據(jù)拌屏∽辏可以用來存放另外一個message忍坷。
}

編譯

把protoc編譯成java文件

官方的語法是這樣的憎兽。

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto

我自己的做法比較簡單一點屹耐。
cd到proto文件的目錄燃领,然后輸入

protoc --java_out=ProtoBuffer prototest.proto
  • ProtoBufferjava文件生成的文件夾颗味。
  • prototest.proto是proto文件舔亭。
  • 如果是生成其他類型的文件脖律,只需要把java_out替換成對應(yīng)的cpp_out,csharp_out等即可谢肾。指令可以通過輸入protoc -help瀏覽。

在java中使用

首先小泉,需要把上面得到的jar包放到lib里面芦疏。把得到的java文件放到項目中冕杠。

通過以下方式生成一個對象,是的酸茴,如果你沒有寫入任何變量分预。那所有變量的值都是默認值。

Prototest2.SearchRequest searchRequest = Prototest2
                .SearchRequest.newBuilder().build();

然而你只能在生成的時候賦值薪捍。笼痹。

Prototest2.SearchRequest searchRequest = Prototest2
                .SearchRequest.newBuilder()
                .setQuery("hhh")
                .setPageNumber(2)
                .setData(book.toByteString())//book是另外一個proto對象
                .setType(Prototest2.SearchRequest.Type.SLOW_SEARCH)//設(shè)置枚舉類型
                .build();

上面可以看到,我們可以通過toByteString()把proto對象轉(zhuǎn)成byteString類型的數(shù)據(jù)酪穿。而對應(yīng)的凳干,可以把byteString數(shù)據(jù)通過parseFrom轉(zhuǎn)化為proto對象。

Prototest3.Book book1 = Prototest3.Book.parseFrom(searchRequest.getData());
寫到流中

通過writeTo方法被济,把消息寫入輸出流中

writeTo(OutputStream output)

這個方法只是writeTo(CodedOutputStream)方法的包裝方法救赐。同樣地,這個方法不會flush或者close流只磷。

注意:brotobuf不會自限制(?)经磅,所以如果你在這個消息之后又在同一個流里面wirte了其他的信息,那你必須做一些操作去確定哪一部分是brotobuf喳瓣。例如馋贤,你可以在這個消息之前發(fā)送數(shù)據(jù)的大小,然后確認這個消息到什么地方為止畏陕∨渑遥或者,直接使用writeDelimitedTo(OutputStream)惠毁。

writeDelimitedTo(OutputStream)
和writeTo(OutputStream output)一樣犹芹,不過會用varint的方法在數(shù)據(jù)之前寫一下數(shù)據(jù)的大小。這就允許在同一個流里面寫更多數(shù)據(jù)了鞠绰。Use MessageLite.Builder.mergeDelimitedFrom(InputStream) (or the static method YourMessageType.parseDelimitedFrom(InputStream)) to parse messages written by this method.

從流中讀取
Prototest2.SearchRequest.parseDelimitedFrom(inputStream);  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腰埂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜈膨,更是在濱河造成了極大的恐慌屿笼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,423評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翁巍,死亡現(xiàn)場離奇詭異驴一,居然都是意外死亡,警方通過查閱死者的電腦和手機灶壶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,147評論 2 385
  • 文/潘曉璐 我一進店門肝断,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事胸懈〉F耍” “怎么了?”我有些...
    開封第一講書人閱讀 157,019評論 0 348
  • 文/不壞的土叔 我叫張陵趣钱,是天一觀的道長涌献。 經(jīng)常有香客問我,道長羔挡,這世上最難降的妖魔是什么洁奈? 我笑而不...
    開封第一講書人閱讀 56,443評論 1 283
  • 正文 為了忘掉前任间唉,我火速辦了婚禮绞灼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呈野。我一直安慰自己低矮,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,535評論 6 385
  • 文/花漫 我一把揭開白布被冒。 她就那樣靜靜地躺著军掂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昨悼。 梳的紋絲不亂的頭發(fā)上蝗锥,一...
    開封第一講書人閱讀 49,798評論 1 290
  • 那天,我揣著相機與錄音率触,去河邊找鬼终议。 笑死,一個胖子當(dāng)著我的面吹牛葱蝗,可吹牛的內(nèi)容都是我干的穴张。 我是一名探鬼主播,決...
    沈念sama閱讀 38,941評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼两曼,長吁一口氣:“原來是場噩夢啊……” “哼皂甘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悼凑,我...
    開封第一講書人閱讀 37,704評論 0 266
  • 序言:老撾萬榮一對情侶失蹤偿枕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后户辫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體渐夸,經(jīng)...
    沈念sama閱讀 44,152評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,494評論 2 327
  • 正文 我和宋清朗相戀三年寸莫,在試婚紗的時候發(fā)現(xiàn)自己被綠了捺萌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,629評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖桃纯,靈堂內(nèi)的尸體忽然破棺而出酷誓,到底是詐尸還是另有隱情,我是刑警寧澤态坦,帶...
    沈念sama閱讀 34,295評論 4 329
  • 正文 年R本政府宣布盐数,位于F島的核電站,受9級特大地震影響伞梯,放射性物質(zhì)發(fā)生泄漏玫氢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,901評論 3 313
  • 文/蒙蒙 一谜诫、第九天 我趴在偏房一處隱蔽的房頂上張望漾峡。 院中可真熱鬧,春花似錦喻旷、人聲如沸生逸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽槽袄。三九已至,卻和暖如春锋谐,著一層夾襖步出監(jiān)牢的瞬間遍尺,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,978評論 1 266
  • 我被黑心中介騙來泰國打工涮拗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留乾戏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,333評論 2 360
  • 正文 我出身青樓多搀,卻偏偏與公主長得像歧蕉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子康铭,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,499評論 2 348

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