大数据
基础组件

序列化工具:ProtoBuf

简介:ProtocolBuffer是用于结构化数据串行化的灵活、高效、自动的方法,有如XML,不过它更小、更快、也更简单,可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构,甚至可以在无需重新部署程序的情况下更新数据结构。

1. ProtoBuf

ProtocolBuffer是用于结构化数据串行化的灵活、高效、自动的方法,有如XML,不过它更小、更快、也更简单,可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构,甚至可以在无需重新部署程序的情况下更新数据结构。ProtoBuf有以下的优点:

  • 可以使用描述语言、编译器及类库进行串行化和反串行化操作;
  • 它使用高效的二进制编码,易于使用;
  • 它是跨语言的,同时支持多种语言的互操作。

1.1. 编写ProtoBuf描述文件

与Avro相同,ProtoBuf也支持从描述文件构建对象,例如我们有以下的描述文件addressbook.proto:

  • package tutorial;
  • option java_package = "com.coderap.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 phone = 4;
  • }
  • message AddressBook {
  • repeated Person person = 1;
  • }

然后使用ProtoBuf提供的工具进行编译:

  • $ > protoc --java_out . addressbook.proto

即可以在当前目录下生成一个./com/coderap/protobuf/addressbook.java源文件,将这个文件引入我们的Maven工程,就可以直接使用了。

注:ProtoBuf在Maven中的pom依赖如下:

  • <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
  • <dependency>
  • <groupId>com.google.protobuf</groupId>
  • <artifactId>protobuf-java</artifactId>
  • <version>2.5.0</version>
  • </dependency>

1.2. ProtoBuf的常用操作

我们可以使用上面生成的类文件创建对象:

  • Person tom = Person.newBuilder()
  • .setId(12345)
  • .setName("Tom")
  • .setEmail("test@test.com")
  • .addPhone(Person.PhoneNumber.newBuilder()
  • .setNumber("+351 999 999 999")
  • .setType(Person.PhoneType.HOME)
  • .build())
  • .build();

也可以方便的进行串行化操作:

  • // 串行化
  • tom.writeTo(new FileOutputStream("D:/_Note/Code/ProtoBuf/person.data"));
  • System.out.println("Serialize Over");

注:当我们同时将多个对象串行化到一个文件的时候,需要使用writeDelimitedTo()方法,直接使用writeTo()在反串行的时候会报错。

以及反串行操作:

  • // 反串行化
  • Person person = Person.parseFrom(new FileInputStream("D:/_Note/Code/ProtoBuf/person.data"));
  • System.out.println(person);