声明:未经作者允许,禁止转载。
概念
Portocol Buffer是谷歌提出来的一种序列化结构数据的机制,它的可扩展性特别强,支持C++、C#、Java、Go和Python等主流编程语言。使用Portocol Buffer时,仅需要定义好数据的结构化方式,然后就可以使用编译生成的源代码在各种语言各种数据流中写入和读取该结构化数据。
Protocol Buffer的安装
打开Protocol Buffer的Github地址,选择适合自己系统的版本。例如对于windows
系统,可以下载protoc-28.2-win64.zip
,并放置于合适的位置,之后进入bin
目录,可以看到protoc.exe
,将其所在的目录到环境变量中。
然后打开命令行,输入protoc
,若看到如下界面说明安装成功。
使用Protocol Buffer
本节主要介绍Portocol Buffer关于Java的使用案例,其步骤大致为:
- 在
.proto
文件中定义消息格式; - 使用Protocol buffer编译器编译
.proto
文件; - 使用Java API进行消息的读写。
消息的定义
对于要序列化的数据结构,需要在.proto
文件中定义相应的消息格式。
syntax = "proto3"; // 使用proto3语法option java_package = "com.test.protobuf";
option java_outer_classname = "PersonBuf";message Person{string name = 1;int32 age = 2;string id = 3;
}
.proto
文件中支持类似C/C++中的//
和/*...*/
两种注释。
字段说明
在定义域(字段)时,必须为每个定义的字段分配一个在 [ 1 , 536 , 870 , 911 ] [1,536,870,911] [1,536,870,911]的数字,但需要注意的是:
- 消息中不同字段分配的数字必须唯一;
- 数字范围 [ 19 , 000 , 19 , 999 ] [19,000, 19,999] [19,000,19,999]是Protocol Buffer预留的,使用该范围内的保留字段编号会报错;
标量类型
.proto
支持的常用标量类型包括:
.proto 类型 | C++ 类型 | Java 类型 |
---|---|---|
double | double | double |
float | float | float |
int32 | int32 | int |
int64 | int64 | long |
bool | bool | boolean |
string | string | String |
可选项
.proto
文件中一些常用的可选项包括:
java_package
:常用于Java 或 Kotlin代码,用于指定生成的Java类的包名,帮助组织代码;java_outer_classname
:指定生成的外部类的名称。默认情况下,Protobuf会根据文件名生成外部类名;java_multiple_files
:控制是否为每个消息生成独立的Java文件。如果设置为true
,每个消息会被生成到单独的文件中。
编译.Proto
文件
当编译.proto
文件时,编译器会生成你所选择的语言的代码。生成的代码将被用于处理自定义的消息类型,包括获取和设置字段值、序列化和反序列化。
以Java语言为例,编译器为每种消息类型生成一个 .java
文件,并为创建消息类实例提供了一个特殊的 Builder
类。
protoc --java_out=DST_DIR Person.proto
--java_out
用于指定生成的Java文件的输出目录
Java程序中应用
在使用需要在pom.xml
中添加Protobuf
相关的依赖:
<dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>4.28.2</version>
</dependency>
若要构造消息,首先需要构造一个builder
,并设置想要设置的任何字段为自定义的值,然后调用构造器的build()
方法。
PersonBuf.Person person = PersonBuf.Person.newBuilder().setName("Java").setId("1001").setAge(18).build();
System.out.println(person.isInitialized()); // 检查是否已设置所有必填字段
System.out.println(person.toString()); // 返回字符串格式的消息
解析和序列化
Protobuf
关于解析和序列化的方法包括:
方法 | 说明 |
---|---|
byte[] toByteArray() | 序列化消息并返回字节数组 |
static Person parseFrom(byte[] data) | 从给定的字节数组解析消息 |
void writeTo(OutputStream output) | 序列化消息并将其写入OutputStream |
static Person parseFrom(InputStream input) | 从 InputStream 读取并解析消息 |
其所对应的使用示例为:
// 序列化为字节数组
byte[] bytes = person.toByteArray();
PersonBuf.Person person1 = PersonBuf.Person.parseFrom(bytes);
System.out.println(person1.toString());// 序列化并保存
String filename = "src/main/files/Person.bin";
try(FileOutputStream outputStream = new FileOutputStream(filename)){person.writeTo(outputStream);
}catch (IOException e){e.printStackTrace();
}// 反序列化读取构造实例
try(FileInputStream inputStream = new FileInputStream(filename)){PersonBuf.Person person2 = PersonBuf.Person.parseFrom(inputStream);System.out.println(person2.toString());
}catch (IOException e){e.printStackTrace();
}
结语
参考资料
- Protocol Buffers Documentation
以上便是本文的全部内容,若是觉得不错的话可以支持一下,你们的支持是博主继续更新的不竭动力。若发现任何错误,也敬请批评指正!!!