官网:https://github.com/google/protobuf

环境:windows,java

1. protobuf概述
protobuf是Google开发一种数据描述格式,能够将结构化数据序列化,可用于数据存储通信协议等方面。
protobuf是以二进制来存储数据的。相对于JSON和XML具有以下优点:
- 简洁
- 体积小:消息大小只需要XML的1/10 ~ 1/3
- 速度快:解析速度比XML快20 ~ 100倍
- 使用protobuf的编译器,可以生成更容易在编程中使用的数据访问代码
- 更好的兼容性,protobuf设计的一个原则就是要能够很好的支持向下或向上兼容

2. 下载,安装
在使用protobuf之前,需要安装protobuf编译器和运行时环境。
由于protobuf是跨平台,跨语言的,所以需要下载和安装对应版本的编译器和运行时依赖。

(1)protobuf编译器下载:https://github.com/google/protobuf/releases
对于windows平台,下载:protoc-${version}-win32.zip。在此以protoc-3.3.0-win32.zip为例。
解压到指定目录,如:D:\protoc-3.3.0-win32。添加到windows环境变量:D:\protoc-3.3.0-win32\bin。

(2)protobuf运行时下载:protobuf运行时环境是区分不同语言的,针对不同语言的安装方式不同。
下载protobuf到指定目录:git clone https://github.com/google/protobuf.git,如:D:\protobuf。
对于java语言而言,可以通过maven将protobuf运行时依赖安装到本地仓库,详见:https://github.com/google/protobuf/tree/master/java
需要注意的是,在执行:mvn install 之前,需要将protobuf编译器(在此即:D:\protoc-3.3.0-win32\bin\protoc.exe)拷贝到protobuf目录下的src路径下,即:D:\protobuf\src。
否则,在编译安装protobuf运行时环境时报错:

Execute failed: java.io.IOException: Cannot run program ...

cd D:\protobuf\java
mvn install(如果不想执行单元测试,可以执行:mvn install -Dmaven.test.skip=true)

将在maven本地仓库安装protobuf运行时依赖jar包(注意:下载protobuf编译器和运行时环境的版本要保持一致!在此下载的是最新版本:3.3.0),包括:
- protobuf-java: The core Java Protocol Buffers library. Most users only need this artifact.
- protobuf-lite: The lite version of core Java Protobuf Buffers library. It is a subset of the core library and is used together with the 'lite' code generator flag to reduce generated code size for mobile.
- protobuf-java-util: Utilities to work with protos. It contains JSON support as well as utilities to work with proto3 well-known types.

3. 使用protobuf
新建一个空的maven项目,并添加protobuf运行时依赖:
pom.xml:

<dependencies>
<!-- 添加protobuf运行时依赖 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.3.0</version>
</dependency>
</dependencies>

(1)新建protobuf数据描述文件:addressbook.proto

syntax = "proto2";

package tutorial;

option java_package = "org.chench.test.protobuf";
option java_outer_classname = "AddressBookProtos"; message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3; enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
} message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
} repeated PhoneNumber phones = 4;
} message AddressBook {
repeated Person people = 1;
}

编译addressbook.proto,在windows控制台进入addressbook.proto文件所在目录路径下,执行如下编译操作:

protoc -I=. --java_out=. ./addressbook.proto

生成java class:org.chench.test.protobuf.AddressBookProtos.java,将生成的java文件拷贝到前面新建的maven项目中。

(2)保存protobuf序列化数据到文件

package org.chench.test.protobuf;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream; import org.chench.test.protobuf.AddressBookProtos.AddressBook;
import org.chench.test.protobuf.AddressBookProtos.Person;
import org.chench.test.protobuf.AddressBookProtos.Person.PhoneNumber;
import org.chench.test.protobuf.AddressBookProtos.Person.PhoneType; /**
* 使用protobuf类示例: <br />
* 从控制台输入相关信息,然后将数据序列化到文件。
* @desc org.chench.test.protobuf.AddPerson
* @author chench9@lenovo.com
* @date 2017年6月7日
*/
public class AddPerson { static Person PromptForAddress(BufferedReader stdin,
PrintStream stdout) throws IOException {
Person.Builder person = Person.newBuilder(); stdout.print("Enter person ID: ");
person.setId(Integer.valueOf(stdin.readLine())); stdout.print("Enter name: ");
person.setName(stdin.readLine()); stdout.print("Enter email address (blank for none): ");
String email = stdin.readLine();
if(email.length() > 0) {
person.setEmail(email);
} while(true) {
stdout.print("Enter a phone number (or leave blank to finish): "); String number = stdin.readLine();
if(number.length() == 0) {
break;
} PhoneNumber.Builder phoneNumber = PhoneNumber.newBuilder();
phoneNumber.setNumber(number); stdout.print("Is this a mobile, home, or work phone? ");
String type = stdin.readLine();
if("mobile".equalsIgnoreCase(type)) {
phoneNumber.setType(PhoneType.MOBILE);
}else if("home".equalsIgnoreCase(type)) {
phoneNumber.setType(PhoneType.HOME);
}else if("work".equalsIgnoreCase(type)) {
phoneNumber.setType(PhoneType.WORK);
} person.addPhones(phoneNumber);
} return person.build();
} /**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: AddPerson ADDRESS_BOOK_FILE");
System.exit(-1);
} AddressBook.Builder addressBook = AddressBook.newBuilder();
try {
// 从指定文件读取数据
addressBook.mergeFrom(new FileInputStream(args[0]));
} catch (FileNotFoundException e) {
System.out.println(args[0] + ": File not found. Creating a new file.");
e.printStackTrace();
} addressBook.addPeople(PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
System.out)); FileOutputStream out = new FileOutputStream(args[0]);
addressBook.build().writeTo(out);
} }

(3)从protobuf序列化文件中读取之前保存进去的数据。

package org.chench.test.protobuf;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; import org.chench.test.protobuf.AddressBookProtos.AddressBook;
import org.chench.test.protobuf.AddressBookProtos.Person;
import org.chench.test.protobuf.AddressBookProtos.Person.PhoneNumber; /**
* 从protobuf序列化文件读取数据。
* @desc org.chench.test.protobuf.ListPeople
* @author chench9@lenovo.com
* @date 2017年6月7日
*/
public class ListPeople { static void Print(AddressBook addressBook) {
for(Person p : addressBook.getPeopleList()) {
System.out.println("Person ID: " + p.getId());
System.out.println(" Name: " + p.getName());
if (p.hasEmail()) {
System.out.println(" E-mail address: " + p.getEmail());
} for(PhoneNumber pn : p.getPhonesList()) {
switch (pn.getType()) {
case MOBILE:
System.out.print(" Mobile phone #: ");
break;
case HOME:
System.out.print(" Home phone #: ");
break;
case WORK:
System.out.print(" Work phone #: ");
break;
}
System.out.println(pn.getNumber());
}
}
} /**
* @param args
* @throws IOException
* @throws FileNotFoundException
*/
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("Usage: ListPeople ADDRESS_BOOK_FILE");
System.exit(-1);
} try {
AddressBook addressBook = AddressBook.parseFrom(new FileInputStream(args[0]));
Print(addressBook);
} catch (FileNotFoundException e) {
System.out.println(args[0] + ": File not exists");
e.printStackTrace();
} } }

完毕!示例代码详见:https://git.oschina.net/cchanghui/test-protobuf.git

【参考】
http://www.iloveandroid.net/2015/10/08/studyPtorobuf/ protobuf简单使用
https://developers.google.com/protocol-buffers/docs/javatutorial protobuf官方手册

protobuf使用简介的更多相关文章

  1. protobuf语法简介2

    protobuf语法简介2 1.optional的字段和默认值 如上所述,消息描述中的一个元素可以被标记为"可选的"(optional).一个格式良好的消息可以包含0个或一个opt ...

  2. protobuf 语法简介

    protobuf 语法简介 1.基本语义 在.proto文件中,最基本的数据类型为message,如其定义所示,由message引导,之后是message类型的名字,之后是由{}包含的各个域(fiel ...

  3. protobuf框架简介

                         protocolbuffer(以下简称PB)是google 的一种数据交换的格式,它独立于语言,独立于平台.google 提供了三种语言的实现:java.c+ ...

  4. day21 TFRecord格式转换MNIST并显示

    首先简要介绍了下TFRecord格式以及内部实现protobuf协议,然后基于TFRecord格式,对MNIST数据集转换成TFRecord格式,写入本地磁盘文件,再从磁盘文件读取,通过pyplot模 ...

  5. (转)lua protobuffer的实现

    转自: http://www.voidcn.com/article/p-vmuovdgn-bam.html (1)lua实现protobuf的简介 需要读者对google的protobuf有一定的了解 ...

  6. protobuf简介和使用

    1.Protocol Buffers简介 Protocol Buffers (ProtocolBuffer/ protobuf )是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据 ...

  7. 消息中间件NetMQ结合Protobuf简介

    概述 对于稍微熟悉这两个优秀的项目来说,每个内容单独介绍都不为过,本文只是简介并探讨如何将两部分内容合并起来,使其在某些场景下更适合.更高效. NetMQ:ZeroMQ的.Net版本,ZeroMQ简单 ...

  8. protobuf Protocol Buffers 简介 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  9. Protobuf(一)——Protobuf简介

    Protobuf简介 ​ 什么是 Google Protocol Buffer? 假如您在网上搜索,应该会得到类似这样的文字介绍: ​ Google Protocol Buffer( 简称 Proto ...

随机推荐

  1. 利用saltstack批量安装clamav杀毒软件

    源码包安装: clamav_source: file.managed: - name: /tmp/clamav-0.99.2.tar.gz - unless: test -f /tmp/clamav- ...

  2. 【BZOJ5323】[JXOI2018]游戏(组合计数,线性筛)

    [BZOJ5323][JXOI2018]游戏(组合计数,线性筛) 题面 BZOJ 洛谷 题解 显然要考虑的位置只有那些在\([l,r]\)中不存在任意一个约数的数. 假设这样的数有\(x\)个,那么剩 ...

  3. 解决win10“cmd自动弹出一闪而过”问题的方法

    1.禁用CMD win+Q gpedit 打开组策略 用户配置--管理模板--系统--阻止访问命令提示符--已启用. 2.启用PowerShell PS:需要使用CMD时可用powershell代替: ...

  4. luogu2282/bzoj1219 历史年份 (dp+hash+二分+线段树)

    luogu1415 拆分数列的加强版 先考虑弱化版怎么做 设f[i]表示某一串数,最后一个数的右端点是i时,它的左端点的最大值(也就是说,这一串数的最后一个数尽量小) 那么有$f[j]=max\{i+ ...

  5. 洛谷P2468 SDOI 2010 粟粟的书架

    题意:给你一个矩形书架,每个点是这本书的页数,每次询问(x1,y1)(x2,y2)这个小矩形里最少需要取几本书使得页数和等于Hi. 题解:小数据二位前缀和预处理+二分答案,大数据一行所以用主席树做,感 ...

  6. Gnome添加Open with Code菜单

    解决方法 测试环境: Manjaro Linux Rolling at 2018-08-31 19:04:49 Microsoft Visual Stdio Code 1.26.1 Bulid: 20 ...

  7. HEOI2013 Segment

    传说中的“李超树”. 大意:给你若干线段,试求横坐标x上的最上方一条线段的编号.无则输出零. 解:用线段树维护. 插入的时候保存自己这个区间上可能成为最大值的线段,被抛弃的则看情况下放. 查询时从最底 ...

  8. A1126. Eulerian Path

    In graph theory, an Eulerian path is a path in a graph which visits every edge exactly once. Similar ...

  9. bzoj2086 Blocks

    题目链接 题面 思路 可以发现其实就是询问一个最长的区间,使得这个区间的平均数大于等于k.所以将区间内所有数字减去k,然后做一遍前缀和.只要是前缀和之差大于等于0的区间.就是满足条件的. 所以现在问题 ...

  10. windows server 2012 流媒体服务器搭建(直播与点播)

    IIS Live Smooth Streaming(实时平滑流式处理)是微软下一代流媒体解决方案.该技术是在IIS web中集成媒体传输平台IIS media services,实现利用标准 HTTP ...