Google之ProtoBuf简单使用

前言

在学习Netty时,发现可以整合ProtoBuf相关的处理器,所以先来学习一下ProtoBuf相关知识。

关于ProtoBuf

ProtoBuf可以看做一个序列化(对象转成字节数组)和反序列化(字节数组转成对象)工具。相比Java本身的序列化,ProtoBuf可以支持跨语言,如使用Java序列化,使用Python来反序列化。相比XML这个文件格式,ProtoBuf序列化生成的数据更小,传输效率更高。

下载编译器

github地址,这里我们下载windows版本的编译器protoc-3.20.0-win64.zip,解压即可用。

定义proto文件

复制syntax = "proto3";

package tutorial;

option java_package = "com.imooc.sourcecode.java.google.protobuf.test1";
option java_outer_classname = "PersonProto";

message Person {
    optional string name = 1;
    optional int32 email = 2;
    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
    }
    message PhoneNumber {
        optional string number = 1;
        optional PhoneType type = 2;
    }
    repeated PhoneNumber phones = 4;
}

syntax = "proto3" 表示使用proto3版本,默认使用proto2版本。
optional 表示当前字段可选,非必填。
string name = 1 每个字段需要有一个唯一的号码,必须大于0。
enum 表示枚举类型。
repeated 表示可重复,Java中就是List。
message 可以看做一个Java类,可以嵌套。

Java处理

添加maven依赖

复制<dependency>
  <groupId>com.google.protobuf</groupId>
  <artifactId>protobuf-java</artifactId>
  <version>3.19.4</version>
</dependency>
<dependency>
  <groupId>com.google.protobuf</groupId>
  <artifactId>protobuf-java-util</artifactId>
  <version>3.19.4</version>
  <scope>runtime</scope>
</dependency>

根据proto文件创建Java序列化和反序列化代码

复制protoc -I=$SRC_DIR --java_out=$DST_DIR person.proto

-I表示proto文件的路径,--java_out表示生成代码的路径,实际命令为

复制.\protoc.exe -I=D:\java\code_resp\github_resp\source_code\src\main\java\com\imooc\sourcecode\java\google\protobuf\test1 --java_out=D:\java\code_resp\github_resp\source_code\src\main\java person.proto

--java_out值不要包含具体的包路径,proto文件中已经配置了。

将对象序列化到文件中

复制import com.imooc.sourcecode.java.google.protobuf.test1.PersonProto.Person;
import com.imooc.sourcecode.java.google.protobuf.test1.PersonProto.Person.PhoneNumber;
import com.imooc.sourcecode.java.google.protobuf.test1.PersonProto.Person.PhoneType;
import java.io.FileOutputStream;
import java.io.IOException;

public class Client {

  public static void main(String[] args) throws IOException {
    PhoneNumber phoneNumber = PhoneNumber.newBuilder()
        .setNumber("2")
        .setType(PhoneType.HOME)
        .build();
    Person person = Person.newBuilder()
        .setName("lisi")
        .setEmail(12)
        .addPhones(phoneNumber)
        .build();
    person.writeTo(new FileOutputStream("D:/testjar/java_serialize_person"));
  }

}

使用Builder模式创建Person对象并序列化到文件中。

将Python序列化的文件反序列化为对象

复制import com.imooc.sourcecode.java.google.protobuf.test1.PersonProto.Person;
import java.io.FileInputStream;
import java.io.IOException;

public class Client2 {

  public static void main(String[] args) throws IOException {
    Person person = Person.parseFrom(new FileInputStream("D:/testjar/python_serialize_person"));
    System.out.println(person);
  }

}

读取文件并反序列化为对象。

Python处理

安装依赖

复制pip install protobuf

PyCharm中可以这样安装

根据proto文件创建Python序列化和反序列化代码

复制protoc -I=$SRC_DIR --python_out=$DST_DIR person.proto

-I表示proto文件的路径,--python_out表示生成代码的路径,实际命令为

复制.\protoc.exe -I=D:\java\code_resp\PycharmProjects\test_protobuf\protobuf --python_out=D:\java\code_resp\PycharmProjects\test_protobuf\protobuf person.proto 

将Java序列化的文件反序列化为对象

复制import person_pb2


def test_deserialize():
    with open("D:/testjar/java_serialize_person", "r") as rf:
        bytes_read = rf.read()
        person = person_pb2.Person()
        # 需要将字符串转成字节数组
        person.ParseFromString(bytes_read.encode())
        print(person)
    return


if __name__ == "__main__":
    test_deserialize()
    pass

从文件中读取到的是字符串类型,需要转成字节数组类型,核心为ParseFromString()方法。

将对象序列化到文件中

复制import person_pb2


def test_serialize():
    person = person_pb2.Person()
    person.name = "zhangsan"
    person.email = 34
    phone = person.phones.add()
    phone.number = "3"
    phone.type = person.PhoneType.MOBILE
    with open("D:/testjar/python_serialize_person", "wb") as f:
        f.write(person.SerializeToString())
    return


if __name__ == "__main__":
    test_serialize()
    pass

创建一个Person对象并序列化到文件中,核心为SerializeToString()方法。

总结

通过上述测试,我们可以发现,Java序列化的文件通过Python是可以反序列化成功的,Python序列化的文件通过Java也是可以反序列化成功的。更多ProtoBuf相关用法,请查看官方文档

参考

Protocol Buffers
protobuf(proto3)极简入门(python为例)
深入 ProtoBuf - 简介

posted @   strongmore  阅读(932)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示