protocol buffer介紹(protobuf)




1、理論概述
0、參考資料
入門資料:https://developers.google.com/protocol-buffers/docs/javatutorial
更詳細的資料:
For more detailed reference information, see the Protocol Buffer Language Guide, the Java API Reference, the Java Generated Code Guide, and the Encoding Reference.


一、protobuf是什麼?
看看官方的解釋
   Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages.
也就是說:protobuf是一個google的開源項目,它是一個語言獨立、平臺獨立,可擴展的數據序列化機制,相似於XML,但它更小、更快和更簡單。

二、protobuf能作什麼?
很明顯,它可用於對象序列化與反序列化,主要用於數據存儲與數據傳輸格式的定義。
目前被大量用於hadoop的RPC通訊協議中,全部的RPC函數參數均是使用protobuf定義的。

三、與XML相比的優缺點
優勢:更小,更快(XML的反序列化效率極低),並且能夠利用工具自動生成代碼。
缺點:因爲用二進制保存數據,致使可讀性差    

2、API
一、使用protobuf的基本步驟以下:
(1)定義消息的格式(通常使用.proto後綴)
(2)使用protobuf提供的compiler,根據.proto文件生成類
(3)使用API進行消息的讀寫

二、定義消息的格式(通常使用.proto後綴)html

 

package tutorial;

option java_package = "org.ljh.protobufdemo";
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 phone = 4;
}

message AddressBook {
  repeated Person person = 1;
}

 

 

 

proto文件說明,完整說明請見https://developers.google.com/protocol-buffers/docs/proto
(1)package用於指明命名空間,以防與其它項目衝突。
(2)若是指定java_package,則它做爲下一步要生成的java類的package,不然package中定義的值將做爲java類的package。
(3)java_outer_classname指定了生成類的類名,若是沒指定,則使用.proto文件的文件名做爲類名。
(4)message表示消息定義,消息之間能夠互相嵌套或者調用。
(5)每一個字段後的等號定義的是該字段的tag,因爲1~15少用了一個字節,所以,這些標籤最好留給用得不少的字段,尤爲是使用repeated定義的字段。
(6)每一個字段必須使用如下3個修飾符之一:required, optional, repeated。

三、從標準輸入中讀入信息,構建person,而後序列化到一個文件中java

package org.ljh.protobufdemo;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;

import org.ljh.protobufdemo.AddressBookProtos.AddressBook;
import org.ljh.protobufdemo.AddressBookProtos.Person;

public 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.addPhone(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 {
    if (args.length != 1) {
      System.err.println("Usage:  AddPerson ADDRESS_BOOK_FILE");
      System.exit(-1);
    }

    AddressBook.Builder addressBook = AddressBook.newBuilder();

    // Read the existing address book.
    try {
      addressBook.mergeFrom(new FileInputStream(args[0]));
    } catch (FileNotFoundException e) {
      System.out.println(args[0] + ": File not found.  Creating a new file.");
    }

    // Add an address.
    addressBook.addPerson(
      PromptForAddress(new BufferedReader(new InputStreamReader(System.in)),
                       System.out));

    // Write the new address book back to disk.
    FileOutputStream output = new FileOutputStream(args[0]);
    addressBook.build().writeTo(output);
    output.close();
  }
}



四、從文件中讀取內容,而後反序列化到一個實例ide

package org.ljh.protobufdemo;


import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;

import org.ljh.protobufdemo.AddressBookProtos.AddressBook;
import org.ljh.protobufdemo.AddressBookProtos.Person;

public class ListPeople {
  // Iterates though all people in the AddressBook and prints info about them.
  static void Print(AddressBook addressBook) {
    for (Person person: addressBook.getPersonList()) {
      System.out.println("Person ID: " + person.getId());
      System.out.println("  Name: " + person.getName());
      if (person.hasEmail()) {
        System.out.println("  E-mail address: " + person.getEmail());
      }

      for (Person.PhoneNumber phoneNumber : person.getPhoneList()) {
        switch (phoneNumber.getType()) {
          case MOBILE:
            System.out.print("  Mobile phone #: ");
            break;
          case HOME:
            System.out.print("  Hls"
                    + "ome phone #: ");
            break;
          case WORK:
            System.out.print("  Work phone #: ");
            break;
        }
        System.out.println(phoneNumber.getNumber());
      }
    }
  }

  // Main function:  Reads the entire address book from a file and prints all
  //   the information inside.
  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage:  ListPeople ADDRESS_BOOK_FILE");
      System.exit(-1);
    }

    // Read the existing address book.
    AddressBook addressBook =
      AddressBook.parseFrom(new FileInputStream(args[0]));

    Print(addressBook);
  }
}
相關文章
相關標籤/搜索