zoukankan      html  css  js  c++  java
  • ProtoBuf初体验

    ProtoBuf初体验

    ProtoBuf介绍

    定义

    protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。

    与XML和JSON对比

    1.序列化后体积相比Json和XML很小,适合网络传输

    2.支持跨平台多语言

    3.消息格式升级和兼容性还不错

    4.序列化反序列化速度很快,快于Json的处理速度快

    特点

    1.语言无关、平台无关。即 ProtoBuf 支持 Java、C++、Python 等多种
    语言,支持多个平台
    2.高效。
    3.扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程

    .proto 文件

    定义

    使用 proto语法编写的文本文件, 用来定义数据格式。

    作用

    当你使用protobuf编译器编译一个.proto文件,它会生成在.proto内你描述的消息类型的操作代码,这些代码是根据你所选择的编程功能语言决定的。这些操作代码内包含了设置字段值和读取字段值,以及序列化到输出流和从输入流反序列化。

    示例

    addressbook.proto

    // See README.txt for information and build instructions.
    //
    // Note: START and END tags are used in comments to define sections used in
    // tutorials.  They are not part of the syntax for Protocol Buffers.
    //
    // To get an in-depth walkthrough of this file and the related examples, see:
    // https://developers.google.com/protocol-buffers/docs/tutorials
    
    // [START declaration]
    syntax = "proto3";
    package tutorial;
    
    import "google/protobuf/timestamp.proto";
    // [END declaration]
    
    // [START java_declaration]
    option java_package = "com.example.tutorial";
    option java_outer_classname = "AddressBookProtos";
    // [END java_declaration]
    
    // [START csharp_declaration]
    option csharp_namespace = "Google.Protobuf.Examples.AddressBook";
    // [END csharp_declaration]
    
    // [START messages]
    message Person {
      string name = 1;
      int32 id = 2;  // Unique ID number for this person.
      string email = 3;
    
      enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
      }
    
      message PhoneNumber {
        string number = 1;
        PhoneType type = 2;
      }
    
      repeated PhoneNumber phones = 4;
    
      google.protobuf.Timestamp last_updated = 5;
    }
    
    // Our address book file is just one of these.
    message AddressBook {
      repeated Person people = 1;
    }
    // [END messages]
    

    protobuf 编译器(compile)

    作用

    将 proto 文件编译成不同语言的实现, 这样不同语言中的数据就可以用 protobuf 格式的数据进行交互。

    不同语言编译后说明

    C++:编译器会按照每个.proto文件生成与其对应的.h和.cc文件,每个消息类似 都有独立的消息操作类。
    Java:编译器将会生成一个.java文件和一个操作类,此操作类为所有消息类型所共有, 使用一个特别的Builder类为每个消息类型实例化。
    Python:有一点不同 – 编译器会为每个消息生成一个模块每个模块有一个静态描述符, 该模块与一个元类在运行时创建一个所需数据操作类。

    Java举例

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

    生成AddressBookProtos.java文件和对应的目录结构:

    protobuf 运行时(runtime)

    作用

    protobuf 运行时所需要的库,包括生成代码中依赖的库和操作生成代码的库。

    Java运行时依赖

    <!--If you are using Maven, use the following:-->
    
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java</artifactId>
      <version>3.11.0</version>
    </dependency>
    
    <!--
    Make sure the version number of the runtime matches (or is newer than) the version number of the protoc.
    If you want to use features like protobuf JsonFormat, add a dependency on the protobuf-java-util package:
    -->
    <dependency>
      <groupId>com.google.protobuf</groupId>
      <artifactId>protobuf-java-util</artifactId>
      <version>3.11.0</version>
    </dependency>
    

    Java使用ProtoBuf生成代码

    class AddPerson {
        // This function fills in a Person message based on user input.
        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;
                }
    
                Person.PhoneNumber.Builder phoneNumber =
                        Person.PhoneNumber.newBuilder().setNumber(number);
    
                stdout.print("Is this a mobile, home, or work phone? ");
                String type = stdin.readLine();
                if (type.equals("mobile")) {
                    phoneNumber.setType(Person.PhoneType.MOBILE);
                } else if (type.equals("home")) {
                    phoneNumber.setType(Person.PhoneType.HOME);
                } else if (type.equals("work")) {
                    phoneNumber.setType(Person.PhoneType.WORK);
                } else {
                    stdout.println("Unknown phone type.  Using default.");
                }
    
                person.addPhones(phoneNumber);
            }
    
            return person.build();
        }
    
        // Main function:  Reads the entire address book from a file,
        //   adds one person based on user input, then writes it back out to the same
        //   file.
        public static void main(String[] args) throws Exception {
           String  addressBookPath="./address_book";
            AddressBook.Builder addressBook = AddressBook.newBuilder();
    
            // Read the existing address book.
            try {
                FileInputStream input = new FileInputStream(addressBookPath);
                try {
                    addressBook.mergeFrom(input);
                    System.out.println(addressBook.toString());
                } finally {
                    try { input.close(); } catch (Throwable ignore) {}
                }
            } catch (FileNotFoundException e) {
                System.out.println(args[0] + ": File not found.  Creating a new file.");
            }
    
          /*  // Add an address.
            addressBook.addPeople(
                    PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
                            System.out));
    
            // Write the new address book back to disk.
            FileOutputStream output = new FileOutputStream(addressBookPath);
            try {
                addressBook.build().writeTo(output);
            } finally {
                output.close();
            }*/
        }
    }
    
  • 相关阅读:
    RecyclerView的通用适配器
    Service由浅到深——AIDL的使用方式
    Android热修复——Tinker的集成
    ListView ,GridView 通用适配器
    Android开发者必知的5个开源库
    Android下强制打开键盘
    Android下强制打开软键盘
    怎么监听Android软键盘的打开和关闭
    【转】ListView 3D翻页效果
    Android 手动显示和隐藏软键盘
  • 原文地址:https://www.cnblogs.com/yanshaoshuai/p/12125486.html
Copyright © 2011-2022 走看看