ProtocolBuffers教程

12 篇文章 0 订阅

ProtocolBuffers是Google提出的一种二进制的数据交换格式,性能较平常的XML格式提高了不少.它独立于平台和语言,google提供了C++,Java和Python三种语言的实现,通过第三方扩展可以支持更多的语言平台.现在新版本为2.4.1,但是还只提供2.3.0的protoc编译器下载,新版本需要自行编译了.

一下通过Google提供的例子讲解:

1.编写proto文件

ProtocolBuffers是通过定义.Proto文件做为数据交换的接口.文件中写入需要交换的bean.如:

// See README.txt for information and build instructions.

package tutorial;

// 定义包名
option java_package = "com.example.tutorial";
// 定义类名
option java_outer_classname = "AddressBookProtos";

// 定义message类
message Person {
  required string name = 1;	// required 为必选参数,如果传值为空会抛出IOException
  required int32 id = 2;        // Unique ID number for this person. 
  optional string email = 3;    // optional 为可选参数.

  // 定义枚举类
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {	// 子类
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;	// repeated为可重复参数,通过List实现
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person person = 1;
}

注意:等号不是赋值,而是给字段名分配唯一的数字标签,用于升级时的版本兼容性。

该例子定义了一个AddressBook类.Book类中有多个Person类.


具体内容详见http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/proto.html

2.编译proto文件生成相应语言.

使用protoc进行编译:

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
其他语言输出使用方法:

protoc --java_out . --cpp_out . --python_out . search_response_protos.proto
编译后生成 com/example/tutorial/AddressBookProtos.java的引用类

3.使用proto

分析examples中的AddPerson.java

// See README.txt for information and build instructions.

import com.example.tutorial.AddressBookProtos.AddressBook;
import com.example.tutorial.AddressBookProtos.Person;
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;

class AddPerson {
  // This function fills in a Person message based on user input.
  static Person PromptForAddress(BufferedReader stdin,
                                PrintStream stdout) throws IOException {
    // 构建Builder;类似于StringBuffer的类.
    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);
    }
    // 通过Builder构建返回Message
    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.Builder addressBook = AddressBook.newBuilder();

    // Read the existing address book.
    try {
      FileInputStream input = new FileInputStream(args[0]);
      addressBook.mergeFrom(input);
      input.close();
    } 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();
  }
}
参见: http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/reference/java-generated.html

执行:

javac -d . -classpath .;protobuf-java-2.4.1.jar AddPerson.java ListPeople.java com\example\tutorial\AddressBookProtos.java

报错:

查看AddressBookProtos.java发现2.4.1中GeneratedMessage提供了一个新的空方法需要实现,覆盖该空方法.

重新编译成功,生成class类.

4. 测试

利用接口调用AddPerson添加Person.

java -cp .;protobuf-java-2.4.1.jar AddPerson addr.dat

利用接口调用ListPeople查找添加的Person.

java -cp .;protobuf-java-2.4.1.jar ListPeople addr.dat

5.参考资料

    Google的教程

    二进制编码格式

    关于ProtocolBuffers

    Google Protocol Buffer 的使用和原理

     protobuf和thrift的对比

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值