zoukankan      html  css  js  c++  java
  • 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-win32in。

    (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-win32inprotoc.exe)拷贝到protobuf目录下的src路径下,即:D:protobufsrc。
    否则,在编译安装protobuf运行时环境时报错:

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


    cd D:protobufjava
    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官方手册

  • 相关阅读:
    JavaScript作用域
    原生JS判断作用域输出值
    用原生JS写九九乘法表
    用原生JS写冒泡排序及动画演示
    用原生JS写翻转数组
    用原生JS写星星直角三角形
    rabbitmq系列——(5 消息确认 -- 生产者 事务性消息)
    rabbitmq系列——(5 消息确认 -- 消费者 自动确认和手动确认)
    rabbitmq系列——(6 消息队列集群)
    docker 发布 dotnet3.1 web
  • 原文地址:https://www.cnblogs.com/nuccch/p/6964401.html
Copyright © 2011-2022 走看看