专栏首页后端开发随笔protobuf使用简介

protobuf使用简介

官网: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官方手册

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • yum方式安装mysql

    到https://dev.mysql.com/downloads/repo/yum/ 下载对应操作系统版本的yum仓库,然后进行安装:sudo rpm -Uvh...

    2Simple
  • 前端开发利器之静态服务器

    在进行前端页面开发时,为了调试方便,需要在本地启动一个静态文件服务器,而不需要与后端api服务一起部署。

    2Simple
  • ajax方式下载文件

    在web项目中需要下载文件,由于传递的参数比较多(通过参数在服务器端动态下载指定文件),所以希望使用post方式传递参数。 通常,在web前端需要下载文件,都是...

    2Simple
  • protobuf详解

    protobuf全称Google Protocol Buffers,是google开发的的一套用于数据存储,网络通信时用于协议编解码的工具库。protobuf是...

    用户5521279
  • protobuf相关操作与问题

    JNingWei
  • protobuf简单介绍和ubuntu 16.04环境下安装教程

    protobuf是谷歌的开源序列化协议框架,结构类似于XML,JSON这种,显著的特点是二进制的,效率高,主要用于通信协议和数据存储等方面,算是一种结构化数据...

    砸漏
  • Linux中常用的系统命令

    本期文章主要简单介绍Linux中常用的系统命令,包括:stat、who、whoami、hostname、uname、top、ps、du、df、ifconfig、...

    浩Coding
  • 实现Java热部署的几种解决方案

    happyJared
  • 原理+代码|Python基于主成分分析的客户信贷评级实战

    大样本的数据集固然提供了丰富的信息,但也在一定程度上增加了问题的复杂性。如果我们分别对每个指标进行分析,往往得到的结论是孤立的,并不能完全利用数据蕴含的信息。但...

    刘早起
  • 区块链+VR?用虚拟货币支付,享受亲临般的演唱会体验

    VRPinea

扫码关注云+社区

领取腾讯云代金券