Flat Buffers - 快速指南
Flat Buffers - 简介
在介绍Flat Buffers之前,让我们先简单了解一下序列化的背景,这就是Flat Buffers的作用。
什么是序列化和反序列化?
每当我们需要将对象状态保存到内存系统时,我们都需要序列化。在序列化中,我们将对象转换为字节并将字节存储在内存系统中。然后可以对这些存储的字节进行反序列化以恢复对象状态。当我们将对象转换为字节时,它可以存储在任何地方,包括文件系统、消息队列、数据库等,然后我们可以将这些字节传输到不同的机器并检索对象状态。
为什么我们需要序列化和反序列化?
序列化有助于保存对象状态,然后我们可以通过网络将其传输到任何地方。一旦收到,我们就可以反序列化对象,换句话说,我们可以随时从不同机器上的字节恢复我们的对象。这是序列化和反序列化的许多重要用例之一。另一个重要用例是通过网络传输对象。消息队列、数据库对象、REST API 都遵循此原则。在这种情况下,对象首先由发送方序列化,然后传输给接收方。然后,接收方反序列化序列化的对象。
在 REST API、微服务架构中,应用程序通常被分解为小型服务,这些服务通过消息队列和 API 相互通信。由于通信是通过网络进行的,需要频繁将对象转换为字节并转换回对象。因此,当涉及到分布式环境时,序列化和反序列化就变得非常关键。
为什么是Flat Buffers?
Google Flat Buffers 将对象序列化和反序列化为可以通过网络传输的字节。但是,还有一些其他库和机制可以传输数据。
那么,Flat Buffers 有什么特别之处?以下是它的一些重要功能 −
语言独立 − Flat Buffers 编译器可以为许多语言创建代码,如 Java、Python、Go、C、C++ 等。因此,Java 对象可以从 Java 程序序列化为字节,并可以反序列化为 Python 对象,反之亦然。
高效数据压缩 − 最初是为游戏环境和性能关键型系统开发的,Flat Buffers API 在设计时考虑到了数据压缩和性能。它非常节省内存,甚至比另一个用于序列化和反序列化的 Google 库 Google Protocol Buffers 更快。
向后和向前兼容性 −Flat Buffers架构既向后兼容,又向前兼容。Flat Buffers的架构支持在较新的代码中添加更改,并允许弃用较旧的更改而不会破坏向后兼容性。
易于使用 − Flat Buffers 库自动生成序列化代码(我们将在接下来的章节中看到),具有版本控制方案,以确保数据创建者和数据用户可以拥有不同版本的序列化定义等。
JSON 可转换 Flat buffers 模式文件可以转换为 JSON 文件,同样,我们可以使用 flat buffers 模式转换 JSON 文件。
Flat Buffers 与其他(XML/JSON/Java 序列化)
让我们看看其他通过网络传输数据的方式与 Flat Buffers 相比如何。
功能 | Flat Buffers | JSON | XML |
---|---|---|---|
与语言无关 | 是 | 是 | 是 |
序列化数据大小 | 三者中最小 | 小于 XML | 三者中最高 |
人类可读性 | 否,因为它使用单独的编码模式 | 是,因为它使用基于文本的格式 | 是,因为它使用基于文本的格式 |
序列化速度 | 三者中速度最快 | 比...快XML | 三者中最慢 |
数据类型支持 | 比其他两个更丰富。支持复杂的数据类型,如 Any、one of 等。 | 支持基本数据类型 | 支持基本数据类型 |
支持不断发展的架构 | 是 | 否 | 否 |
Flat Buffers - 架构
概述
现在让我们使用 Google Flat Buffers,看看它如何与简单的 Greeting 应用程序配合使用。在这个例子中,我们将创建一个简单的应用程序,它将执行以下操作 −
问候编写器
从用户那里获取问候语和用户名
将上述信息存储在磁盘上的文件中
问候阅读器
读取我们存储在上述文件中的相同文件
将该数据转换为对象并打印数据
Flat Buffers模式文件
Flat Buffers"模式文件"包含我们要序列化的数据的模式定义。数据存储在扩展名为 ".fbs" 的人类可读文件中。
让我们将以下数据存储在 greeting.fbs 中,我们将在我们的第一个应用程序中使用它。
greeting.fbs
namespace com.tutorialspoint.greeting; table Greet { greeting: string; username: string; } root_type Greet;
了解每个构造
namespace com.tutorialspoint.greeting;
此处的 namespace 用于从 .fbs 文件生成的代码的包/命名空间声明。例如,我们生成的 java 类将位于 com.tutorialspoint.greeting 包中。
table Greet
将要创建/重新创建的对象的基类的名称。
greeting: string; username: string;
这些是 Greet 类的属性以及数据类型。
root_type Greet;
root_type 告知 flat buffers 编译器根表是 Greet,在生成代码时将作为主类。
Flat Buffers 代码生成
现在我们已经定义好了,让我们安装"flatc"二进制文件,我们将使用它来自动生成上述 Greet 类的代码。二进制文件可在 "https://github.com/google/flatbuffers/releases" 找到。
根据操作系统选择正确的二进制文件。我们将在 Windows 上安装 flat buffers 编译器二进制文件,但对于 Linux,步骤没有太大不同。
我们已下载 https://github.com/google/flatbuffers/releases/download/v24.3.25/Windows.flatc.binary.zip
验证 Flat Buffers 编译器设置
安装后,请确保您可以通过命令行访问它 −
flatc --version flatc version 24.3.25
它确认 Flatc 已正确安装。现在让我们转到 创建 上面描述的 Java 问候应用程序。
Java 中的问候应用程序
现在我们已经安装了 flatc,我们可以使用 flatc 从 fa 文件自动生成代码。让我们先创建一个 Java 项目。
以下是我们将用于 Java 项目的 Maven 配置。请注意,它还包含 flatc-java 所需的库。
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.tutorialspoint.greeting</groupId> <artifactId>flatbuffers-tutorial</artifactId> <version>1.0</version> <packaging>jar</packaging> <properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> </properties> <dependencies> <!-- https://mvnrepository.com/artifact/com.google.flatbuffers/flatbuffers-java --> <dependency> <groupId>com.google.flatbuffers</groupId> <artifactId>flatbuffers-java</artifactId> <version>24.3.25</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.2.4</version> <configuration> <!--Put your configurations here--> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
我们所有的代码都位于 src/main/java 下。
项目结构搞定后,让我们为 Greet 类生成代码 −
生成 Java 类
flatc --java Greeting.fbs
执行命令后,您会注意到 com > tutorialspoint > 下有一个自动生成的类当前目录中的问候 文件夹。
Greet.java
此文件包含一个类 Greet,可帮助我们对 Greet 对象进行序列化和反序列化。
使用生成的 Java 类
现在,让我们 编写 数据的编写器,它将以 用户名 和 问候 作为其输入 −
GreetWriter.java
package com.tutorialspoint.greeting; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class GreetWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建 Greet FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 从控制台读取问候语和用户名 int Greeting = builder.createString(args[0]); int username = builder.createString(args[1]); // 使用 startGreet() 方法创建 Greet FlatBuffers Greet.startGreet(builder); // 将问候语和用户名添加到 Greet FlatBuffer 中 Greet.addGreeting(builder, greeting); Greet.addUsername(builder, username); // 标记在 Gret FlatBuffer 中输入数据的结束 int greet = Greet.endGreet(builder); // 完成构建器 builder.finish(greet); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "greeting_flatbuffers_output"; System.out.println("Saving greeting to file: " + filename); // write the builder content to the file named greeting_flatbuffers_output try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved greeting with following data to disk: " + greeting); } }
writer 仅接受 CLI 参数,创建 Greet 对象,对其进行序列化,然后将其转储到文件中。
现在让我们编写一个 reader 来读取文件 −
GreetReader.java
package com.tutorialspoint.greeting; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class GreetReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "greeting_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Greet greet = Greet.getRootAsGreet(buf); // 打印 greet 值 System.out.println("Greeting: " + greet.greeting() + " " + "Username: " + greet.username()); } } }
reader 只是从同一个文件中读取数据,对其进行反序列化,然后打印有关问候语的数据。
编译项目
现在我们已经设置了 reader 和 writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,让我们首先执行 writer 将对象序列化到文件系统。
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.greeting.GreetWriter Hello John Saving greeting to file: greeting_protobuf_output Saved greeting with following data to disk: 12
反序列化序列化对象
然后,让我们执行读取器从文件系统反序列化对象。
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.greeting.GreetReader Reading from file greeting_protobuf_output Greeting: Hello Username: John
因此,当我们看到由 writer 序列化并保存到文件的数据时,该确切数据已由 reader 正确反序列化并相应地打印。
Flat Buffers - 构造
概述
现在让我们看看 Google Flat Buffers 提供的一些基本数据结构和数据类型。我们将使用电影院的示例来查看这些数据结构。
请注意,对于此结构,虽然我们将使用 Java 代码,但在 Python 代码中使用它们也应该同样简单且可行。
在接下来的几章中,我们将逐一讨论以下 Flat Buffers 数据类型 −
数据类型
table − "table" 是 Flat Buffers 的一个非常基本的构建块。这在我们使用的语言中转换为类,例如 Java、Python 等
string − "string" 数据类型在我们使用的语言中转换为字符串,例如 Java、Python 等
Numbers − Numbers 包括 Flat Buffers 类型,如 int、short、float、double,它们是 Protobuf 的基本构建块。它在我们使用的语言中分别转换为 int、long float、double,例如 Java、Python 等。我们也可以使用别名,例如 int16 表示 short,float32 表示 float 等。
bool − "bool" 数据类型是 Flat Buffers 的基本构建块之一。它在我们使用的语言中转换为布尔值,例如 Java、Python 等。
枚举 − "枚举"是 Flat Buffers 的复合数据类型之一。它在我们使用的语言中转换为枚举,例如 Java。
向量 − [] 表示法用于创建向量或数组,是 Flat Buffers 的复合数据类型之一。Flat Buffers 向量类似于 java 数组。
结构 − "结构"是 Flat Buffers 的复合数据类型之一。它用于创建不可修改的标量值集。结构使用更少的内存并且查找速度非常快。
嵌套类 −我们可以在另一个"表"中使用使用"表"创建的类,从而创建一个嵌套类。
union − "union"用于创建可以接受任何不同类型值的结构。
Flat Buffers - table
概述
Flat Buffers 的最基本构建块是 table 属性。这相当于我们使用的语言中的 class,例如 Java、Python 等。
示例代码
以下是我们需要的语法,用于指示 Flat Buffers 我们将创建给定表的实例−
namespace com.tutorialspoint.theater; table Theater { } root_type Theater;
我们将上述内容保存在"theater.fbs"中,并在探索其他数据结构时使用它。
解释
namespace com.tutorialspoint.theater;
此参数特定于 Java,即,将自动生成来自".fbs"文件的代码的包。类 Theater 将在com.tutorialpoint.theater包中创建。
接下来,我们创建一个表,Theater −
table Theater
这只不过是将要创建/重新创建的对象的基类的类名。请注意,它在当前形状下是无用的,因为它没有任何其他属性。但随着我们的前进,我们将添加更多属性。
使用多个表属性
单个 fbs 文件也可以有多个表。例如,如果我们愿意,我们可以在同一个文件中添加 Visitor 表。Flat Buffers 将确保 Theater 类使用 root_type 属性保持主类。例如 −
namespace com.tutorialspoint.theater; table Theater { } table Visitor { } root_type Theater;
从 fbs 文件创建 Java 类
要使用 Flat Buffers,我们现在必须使用 flat 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flat --java theater.fbs
使用从 fbs 文件创建的 Java 类
好了,就是这样!上述命令应在当前目录中创建所需的文件,现在我们可以在 Java 代码中使用它们 −
// 使用默认缓冲区创建 FlatBuffer Builder FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder);
在此阶段,它不是很有用,因为我们没有向表中添加任何属性。让我们在Flat Buffers - string一章中查看字符串时这样做。
Flat Buffers - string
概述
Flat Buffers 字符串会转换为我们使用的语言中的字符串,例如 Java、Python 等。继续theater示例,以下是我们需要指示 Flat Buffers 我们将创建字符串的语法 −
theater.fbs
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; } root_type Theater;
现在我们的 table 包含两个 string 属性。每个属性的默认值为 null。
从 fbs 文件创建 Java 类
要使用 Flat Buffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建一个 Theater.java 类。我们在应用程序中使用此类的方式类似于 Flat Buffers - Schema 一章中所做的那样。
使用从 fbs 文件创建的 Java 类
首先让我们创建一个 writer 来写入 theater 信息−
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); int name = builder.createString("Silver Screener"); int address = builder.createString("212, Maple Street, LA, California"); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // add the name and address to the Theater FlatBuffer Theater.addName(builder, name); Theater.addAddress(builder, address); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Name: " + theater.name() + " " + "Address: " + theater.address()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 72
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的字符串。现在让我们在下一章 Flat Buffers - Numbers 中查看 numbers。
Flat Buffers - Numbers
概述
Numbers 包括 flatbuffers 类型,如 int、short、float、double,它们是 Flat Buffers 的基本构建块。在我们所使用的语言(例如 Java、Python 等)中,它分别转换为 int、short float、double。
继续使用 Flat Buffers - String 一章中的 theater 示例,以下是我们需要用来指示 Flat Buffers 创建 数字 的语法−
theater.fbs
namespace com.tutorialspoint.theater; table Theater { total_capcity:int; mobile:long; base_ticket_price:float; } root_type Theater;
现在我们的表包含数字属性。默认值为 0 或 0.0(视情况而定)。
从 FBS 文件创建 Java 类
要使用 Flat Buffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何执行此操作 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建一个 Theater.java 类。我们在应用程序中使用此类的方式类似于在 Flat Buffers - Schema 一章中所做的那样。
<使用从 fbs 文件创建的 Java 类
首先让我们创建一个 writer 来写入 theater 信息−
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); int totalCapacity = 320; long mobile = 98234567189L; float baseTicketPrice = 22.45f; // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addTotalCapcity(builder, totalCapacity); Theater.addMobile(builder, mobile); Theater.addBaseTicketPrice(builder, baseTicketPrice); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Total Capacity: " + theater.totalCapcity() + " " + "Mobile: " + theater.mobile() + " " + "Base Ticket Price: " + theater.baseTicketPrice()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 24
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Total Capacity: 320 Mobile: 98234567189 Base Ticket Price: 22.45
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的字符串。现在让我们在下一章 Flat Buffers - bool 中查看 数字。
Flat Buffers - Boolean
概述
bool 数据类型是 Flat Buffers 的基本构建块之一。在我们所使用的语言中,它被翻译为 Boolean,例如 Java、Python 等。
继续使用 Flat Buffers - String 章节中的 theater 示例,以下是我们需要用来指示 Flat Buffers 创建 bool 的语法 −
theater.fbs
namespace com.tutorialspoint.theater; table Theater { drive_in:bool; } root_type Theater;
现在我们的 table 包含一个 bool 属性。默认值为 false。
从 FBS 文件创建 Java 类
要使用 Flat Buffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录中的 com > tutorialspoint > theater 文件夹中创建一个 Theater.java 类。我们在应用程序中使用此类的方式与Flat Buffers - Schema一章中的方式类似。
使用从 fbs 文件创建的 Java 类
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); boolean driveIn = true; // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addDriveIn(builder, driveIn); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Drive In: " + theater.driveIn()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 8
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Drive In: true
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的字符串。现在让我们在下一章 Flat Buffers - Enum 中查看 numbers。
Flat Buffers - enum
概述
enum 数据类型是 Flat Buffers 的复合数据类型之一。它相当于我们使用的语言中的 枚举,例如 Java 等。
继续使用 Flat Buffers - String 章节中的 theater 示例,以下是我们需要用来指示 FlatBuffers 我们将创建 枚举 的语法 −
theater.fbs
namespace com.tutorialspoint.theater; enum PAYMENT_SYSTEM: byte { CASH = 0, CREDIT_CARD = 1, DEBIT_CARD, APP = 3 } table Theater { payment:PAYMENT_SYSTEM; } root_type Theater;
现在我们的表包含一个枚举属性。我们为每个枚举常量分配了一个值,除了一个 DEBIT_CARD,默认情况下,它采用增量值 2。
我们定义枚举并将其用作下面的数据类型以及"payment"属性。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用flatc二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的com > tutorialspoint > theater 文件夹中创建一个 Theater.java 和 PAYMENT_SYSTEM 类。我们在应用程序中使用此类的方式与Flat Buffers - Schema一章中的方式类似。
使用从 fbs 文件创建的 Java 类
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addPayment(builder, PAYMENT_SYSTEM.DEBIT_CARD); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Payment Method: " + theater.payment()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
> java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater information to file: theater_flatbuffers_output Saved theater information with following data to disk: 8
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Payment Method: 2
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的 enum。在下一章 Protocol Buffers - Vector 中,我们将研究复合类型向量。
Flat Buffers - Vector
概述
Vector 数据类型是 Flat Buffers 的复合数据类型之一。它相当于我们使用的语言中的数组或列表,例如Java等。
继续Flat Buffers - String一章中的Theater 示例,以下是我们需要用来指示 FlatBuffers 我们将创建一个向量的语法 −
theater.fbs
namespace com.tutorialspoint.theater; table Theater { snacks:[string]; // vector of strings tickets:[float]; // vector of floats } root_type Theater;
现在我们的 table 包含字符串和浮点数的 vector 属性。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录中的 com > tutorialspoint > theater 文件夹中创建一个 Theater.java 类。我们在应用程序中使用此类的方式与 Flat Buffers - Schema 一章中的方式类似。
使用从 fbs 文件创建的 Java 类
创建和写入向量
为了创建向量,我们首先需要准备标量类型数组的偏移量,然后我们可以将向量添加到Flat Buffers。
// 为字符串数组创建数据 int popcorn = builder.createString("Popcorn"); int coke = builder.createString("Coke"); int chips = builder.createString("Chips"); int soda = builder.createString("Soda"); // 为snacks(零食)创建数组 int[] snacks = {popcorn, coke, chip, soda}; // 为snacks(零食)向量创建偏移量 int snacksVector = Theater.createSnacksVector(builder, snacks); // 向Theater FlatBuffer 添加详细信息 Theater.addSnacks(builder, snacksVector);
以下示例代码展示了创建字符串和整数向量的过程。
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 为字符串数组创建数据 int popcorn = builder.createString("Popcorn"); int coke = builder.createString("Coke"); int chips = builder.createString("Chips"); int soda = builder.createString("Soda"); // 创建snacks(零食)数组 int[] snacks = {爆米花、可乐、薯片、苏打水}; // 创建票数数组 float[] tickets = {100.0f, 100.f, 200.f}; // 创建snacks(零食)向量偏移量 int snacksVector = Theater.createSnacksVector(builder, snacks); // 创建票数向量偏移量 int ticketsVector = Theater.createTicketsVector(builder, tickets); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addSnacks(builder, snacksVector); Theater.addTickets(builder, ticketsVector); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
读取向量
为了读取向量,我们有方法获取向量的长度并通过索引获取条目,如下所示。
// 迭代由 snacksLength() 方法确定长度的snacks(零食)向量 for(int i = 0; i < theater.snacksLength(); i++ ) { // 通过其索引获取snacks(零食) System.out.print(" " + theater.snacks(i)); }
以下示例代码显示了读取字符串和整数向量的过程。
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Snacks: "); for(int i = 0; i < theater.snacksLength(); i++ ) { System.out.print(" " + theater.snacks(i)); } System.out.println(" Tickets: "); for(int i = 0; i < theater.ticketsLength(); i++ ) { System.out.print(" " + theater.tickets(i)); } } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
> java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater information to file: theater_flatbuffers_output Saved theater information with following data to disk: 96
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Snacks: Popcorn Coke Chips Soda Tickets: 100.0 100.0 200.0
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的 vector。在下一章 Flat Buffers - struct 中,我们将介绍扇区,这是一种复合类型。
Flat Buffers - struct
概述
struct 数据类型是 Flat Buffers 的复合数据类型之一。它用于创建不可变的数据结构。结构占用的内存较少,查找速度相当快。结构通常是标量类型的组合。
继续使用 Flat Buffers - String 一章中的 theater 示例,以下是我们需要用来指示 FlatBuffers 创建 struct 的语法 −
theater.fbs
namespace com.tutorialspoint.theater; struct Position { x: int; y: int; z: int; } table Theater { location: Position; } root_type Theater;
现在我们的 table 包含定义为 Position 类型位置的 struct 属性。Position 是一个定义三个 int 数据结构的结构。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建 Theater 和 Position 类。我们在应用程序中使用此类的方式与 Flat Buffers - Schema 一章中的方式类似。
使用从 fbs 文件创建的 Java 类
创建和编写结构体
为了创建结构体,我们首先需要准备标量类型数组的偏移量,然后我们可以将向量添加到Flat Buffers。
// 为位置结构体创建偏移量 int location = Position.createPosition(builder, 100, 110, 120); // 向Theater FlatBuffer 添加详细信息 Theater.addLocation(builder, location);
以下示例代码展示了创建 Ints 结构的过程。
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // create offset for location struct int location = Position.createPosition(builder, 100, 110, 120); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addLocation(builder, location); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
读取结构体
为了读取结构体,我们有方法来获取结构体的每个值。
Position position = theater.location(); System.out.println("x: " + position.x()); System.out.println("y: " + position.y()); System.out.println("z: " + position.z());
以下示例代码显示了读取 int 结构的过程。
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Location: "); Position position = theater.location(); System.out.println("x: " + position.x()); System.out.println("y: " + position.y()); System.out.println("z: " + position.z()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
> java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater information to file: theater_flatbuffers_output Saved theater information with following data to disk: 16
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Location: x: 100 y: 110 z: 120
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的 struct。在下一章 Flat Buffers - union 中,我们将研究 union,一种复合类型。
Flat Buffers - union
概述
union 数据类型是 Flat Buffers 的复合数据类型之一。它用于创建灵活的数据结构,可以采用任何所需的类型。
继续使用 Flat Buffers - String 一章中的 theater 示例,以下是我们需要用来指示 FlatBuffers 创建 union 的语法 −
theater.fbs
namespace com.tutorialspoint.theater; union People { Employee, Viewer } table Theater { people: People; } table Employee { name:string; address:string; id: int; } table Viewer { name: string; address: string; } root_type Theater;
现在我们的表包含定义为两个表 Employee 和 Viewer 的 People 的 union 属性。在 Theater 表中,我们定义了 union 类型的 people,这意味着我们可以将任何 Employee 或 Viewer 存储在 people 变量中。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建 Theater、People、Employee 和 Viewer 类。我们在应用程序中使用此类的方式与 Flat Buffers - Schema 一章中的方式类似。
使用从 fbs 文件创建的 Java 类
创建和编写 Union
为了创建 Union,我们首先需要准备所需类型的偏移量,例如 Viewer,然后我们可以将查看器及其类型添加到Flat Buffers。
// 为 Viewer 创建偏移量 int viewerName = builder.createString("Mery"); int viewerAddress = builder.createString("Avenue 4"); int viewer = Viewer.createViewer(builder, viewerName, viewerAddress); //添加 union 类型 Theater.addPeopleType(builder, People.Viewer); // 向Theater FlatBuffer 添加详细信息 Theater.addPeople(builder, viewer);
以下示例代码展示了创建 Union 的过程。
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 为 Viewer 创建偏移量 int viewerName = builder.createString("Mery"); int viewerAddress = builder.createString("Avenue 4"); int viewer = Viewer.createViewer(builder, viewerName, viewerAddress); // 为向量创建偏移量 //int people = Theater.createPeople // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); //add union type Theater.addPeopleType(builder, People.Viewer); // 向Theater FlatBuffer 添加详细信息 Theater.addPeople(builder, viewer); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
读取 Union
为了读取 Union,我们可以检查 union 对象的类型,然后相应地检索值。
// 获取保存的 union 类型 int unionType = theater.peopleType(); // 如果 union 是 Viewer 类型 if(unionType == People.Viewer) { Viewer viewer = (Viewer)theater.people(new Viewer()); System.out.println("Name: " + viewer.name()); System.out.println("Address: " + viewer.address()); } // 如果 union 是 Employee 类型 else if(unionType == People.Employee) { Employee employee = (Employee)theater.people(new Employee()); System.out.println("Name: " + employee.name()); System.out.println("Address: " + employee.address()); System.out.println("Id: " + employee.id()); }
以下示例代码展示了读取 Union 的过程。
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("People: "); // 获取 union 的类型 int unionType = theater.peopleType(); // 如果 union 是 Viewer 类型 if(unionType == People.Viewer) { Viewer viewer = (Viewer)theater.people(new Viewer()); System.out.println("Name: " + viewer.name()); System.out.println("Address: " + viewer.address()); } else if(unionType == People.Employee) { Employee employee = (Employee)theater.people(new Employee()); System.out.println("Name: " + employee.name()); System.out.println("Address: " + employee.address()); System.out.println("Id: " + employee.id()); } } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
> java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater information to file: theater_flatbuffers_output Saved theater information with following data to disk: 60
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output People: Name: Mery Address: Avenue 4
因此,如我们所见,我们能够通过将二进制数据反序列化为 Theater 对象来读取序列化的 struct。在下一章 Flat Buffers - Nested Tables 中,我们将了解复合类型嵌套表。
Flat Buffers - Nested Table
概述
在这里,我们将了解如何在 Flat Buffers 中创建嵌套表。它相当于一个嵌套的 Java 类。
继续使用 Flat Buffers - String 一章中的 theater 示例,以下是我们需要用来指示 FlatBuffers 创建 嵌套表 的语法 −
theater.fbs
namespace com.tutorialspoint.theater; table Theater { owner: TheaterOwner; } table TheaterOwner { name:string; address:string; } root_type Theater;
现在我们的 Theater 表包含一个嵌套表,即有关Theater 所有者的信息。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录中的 com > tutorialspoint > theater 文件夹中创建 Theater 和 TheaterOwner 类。我们在应用程序中使用此类的方式与Flat Buffers - Schema一章中的方式类似。
使用从 fbs 文件创建的 Java 类
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 为 TheaterOwner 创建偏移量 int ownerName = builder.createString("Mery"); int ownerAddress = builder.createString("Avenue 4"); int owner = TheaterOwner.createTheaterOwner(builder, ownerName, ownerAddress); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addOwner(builder, owner); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Owner Details: "); TheaterOwner owner = theater.owner(); System.out.println("Name: " + owner.name()); System.out.println("Address: " + owner.address()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 56
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Owner Details: Name: Mery Address: Avenue 4
因此,正如我们所见,我们可以通过将二进制数据反序列化为 Theater 对象来读取序列化的嵌套表/对象。
Flat Buffers - 默认值
概述
我们在前面的示例中看到了如何在Flat Buffers中序列化和反序列化各种类型。如果我们不指定任何值,则将存储默认值。如果我们为变量指定了相同的默认值,则 flatbuffers 不会分配额外空间。
Flat Buffers支持其数据类型的默认值,如下表所示 −
数据类型 | 默认值 |
---|---|
int16 / short / int / long | 0 |
Float/double | 0.0 |
String | Empty string |
Boolean | False |
Enum | 第一个枚举项,即"index=0"的项 |
Vector | Empty list |
Nested Class | null |
因此,如果没有为这些数据类型指定数据,则它们将采用上述默认值。现在,让我们继续使用 theater 示例来演示其工作原理。
在此示例中,我们将让所有字段都采用默认值。唯一需要指定的字段是Theater 的名称。
继续使用 Flat Buffers - String 章节中的 theater 示例,以下是我们需要用来指示 FlatBuffers 我们将创建各种数据类型的语法 −
theater.fbs
namespace com.tutorialspoint.theater; enum PAYMENT_SYSTEM: int { CASH = 0, CREDIT_CARD = 1, DEBIT_CARD, APP = 3 } table Theater { name:string; address:string; total_capacity:short; mobile:int; base_ticket_price:float; drive_in:bool; payment:PAYMENT_SYSTEM; snacks:[string]; owner: TheaterOwner; } table TheaterOwner { name:string; address:string; } root_type Theater;
现在我们的 Theater 表包含多个属性。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建 Theater、TheaterOwner 和 PAYMENT_SYSTEM 类。我们在应用程序中使用此类的方式类似于 Flat Buffers - Schema 一章中所做的那样。
使用从 fbs 文件创建的 Java 类
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 为 name 名称创建偏移量 int name = builder.createString("Mery"); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addName(builder, name); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Name: " + theater.name()); System.out.println("Address: " + theater.address()); System.out.println("Total Capacity: " + theater.totalCapacity()); System.out.println("Mobile: " + theater.mobile()); System.out.println("Base Ticket Price: " + theater.baseTicketPrice()); System.out.println("Drive In: " + theater.driveIn()); System.out.println("Snacks: "); if(theater.snacksLength() != 0) { for(int i = 0; i < theater.snacksLength(); i++ ) { System.out.print(" " + theater.snacks(i)); } }else { System.out.println("Snacks are empty."); } System.out.println("Payment Method: " + PAYMENT_SYSTEM.name(theater.payment())); System.out.println("Owner Details: "); TheaterOwner owner = theater.owner(); if(owner != null) { System.out.println("Name: " + owner.name()); System.out.println("Address: " + owner.address()); }else { System.out.println("Owner " + owner); } } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 20
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Mery Address: null Total Capacity: 0 Mobile: 0 Base Ticket Price: 0.0 Drive In: false Snacks: Snacks are empty. Payment Method: CASH Owner Details: Owner null
因此,正如我们所见,我们可以通过将二进制数据反序列化为 Theater 对象来读取默认值。
Flat Buffers - JSON 到二进制
概述
JSON 是一种非常流行的网络数据传输格式。为了提供 JSON 兼容性,Flat Buffers 编译器 flatc 可以选择将源 JSON 转换为Flat Buffers二进制格式,然后可用于反序列化最初由 JSON 表示的对象。
考虑以下携带 Theater 对象信息的 JSON
theater.json
{ "name" : "Silver Screener", "address" : "212, Maple Street, LA, California", "mobile": 12322224 }
theater.fbs
这是我们的 Flat Buffers Schema 文件
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; mobile:int; } root_type Theater;
现在让我们首先使用以下命令根据我们的模式 (theater.fbs) 获取 json 的Flat Buffers二进制表示 (theater.json)。
flatc --binary theater.fbs theater.json
它将在当前文件夹中创建 theater.bin,我们可以读取它以反序列化 Theater 对象。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建一个 Theater 类。我们在应用程序中使用此类的方式与Flat Buffers - Schema一章中的方式类似。
使用从 fbs 文件创建的 Java 类
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater.bin"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Name: " + theater.name()); System.out.println("Address: " + theater.address()); System.out.println("Mobile: " + theater.mobile()); } } }
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater.bin Name: Silver Screener Address: 212, Maple Street, LA, California Mobile: 12322224
因此,正如我们所见,我们可以通过将二进制数据反序列化为 Theater 对象来读取默认值。
Flat Buffers - 二进制到 JSON
概述
JSON 是一种非常流行的网络数据传输格式。为了提供 JSON 兼容性,Flat Buffers 编译器 flatc 可以选择将源 JSON 转换为Flat Buffers二进制格式,然后可以使用该格式反序列化最初由 JSON 表示的对象。我们在上一章Flat Buffers - JSON 到二进制中已经练习过这一点。现在我们将执行反转,从 Flat Buffers 二进制文件中检索 JSON。
考虑上一章 Flat Buffers - JSON to Binary 中创建的 theater.bin 文件。
以下是 flat buffers 编译器正确解释二进制数据所需的模式。
theater.fbs
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; mobile:int; } root_type Theater;
生成 JSON
现在让我们首先使用以下命令从二进制文件 (theater.bin) 中获取所需的 json (theater.json)。
flatc --json --raw-binary theater.fbs -- theater.bin
它将在当前文件夹中创建 theater.json,如下所示。
{ name: "Silver Screener", address: "212, Maple Street, LA, California", mobile: 12322224 }
严格模式
flatc 生成最小 json。如果我们需要使用其他工具处理 JSON,并且需要正确的引用标识符,那么我们可以使用 --strict-json,如下所示:
flatc --json --raw-binary theater.fbs -- theater.bin --strict-json
它将在当前文件夹中创建 theater.json,如下所示。
{ "name": "Silver Screener", "address": "212, Maple Street, LA, California", "mobile": 12322224 }
默认值
默认情况下,flatc 编译器会忽略默认值,默认值不会以二进制表示形式存储。因此这些值也不会以 JSON 形式出现。为了实现这一点,我们可以使用 --defaults-json 选项,如下例所示。
让我们将 mobile 值保留为 json 中的默认值。
theater.json
{ "name" : "Silver Screener", "address" : "212, Maple Street, LA, California", "mobile": 0 }
现在让我们首先使用以下命令根据我们的模式 (theater.fbs) 获取 json 的Flat Buffers二进制表示 (theater.json)。
flatc --binary theater.fbs theater.json
生成没有默认值的 JSON
现在让我们首先使用以下命令从我们的二进制文件 (theater.bin) 获取所需的 json (theater.json)。
flatc --json --raw-binary theater.fbs -- theater.bin
它将在当前文件夹中创建 theater.json,如下所示。
{ name: "Silver Screener", address: "212, Maple Street, LA, California" }
使用默认值生成 JSON
现在使用 --defaults-json 选项生成 JSON。
flatc --json --raw-binary theater.fbs -- theater.bin --defaults-json
它将在当前文件夹中创建 theater.json,如下所示。
{ name: "Silver Screener", address: "212, Maple Street, LA, California", mobile: 0 }
Flat Buffers - 可变缓冲区
概述
每当我们创建一个Flat Buffers文件时,它都是只读的。我们可以使用 flatc 提供的具有 const 访问器的类来读取此文件。这有助于在多个读取器中使用Flat Buffers文件。但有时,我们可能需要在读取后修改某个值,并需要将修改后的值传递给下一个读取器。我们可以通过从头开始创建一个新的Flat Buffers来实现这一点,这对于大的变化来说更好、更高效。对于小改动,Flat Buffers 为 flatc complier 提供了一个选项 --gen-mutable,用于生成非常量访问器来修改 flatbuffers 文件,如下所示:
flatc --java --gen-mutable theater.fbs
示例
请考虑以下架构。
theater.fbs
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; int mobile; } root_type Theater;
从 fbs 文件创建 Java 类
要使用 Flat Buffers,我们现在将使用可变模式下的 flatc 编译器从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java --gen-mutable theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建一个 Theater.java 类。我们在应用程序中使用此类的方式类似于 Flat Buffers - Schema 一章中所做的那样。
使用从 fbs 文件创建的 Java 类
首先让我们创建一个 writer 来写入 theater 信息−
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // 为名字和地址创建偏移量 int name = builder.createString("Silver Screener"); int address = builder.createString("212, Maple Street, LA, California"); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 向Theater FlatBuffer 添加详细信息 Theater.addName(builder, name); Theater.addAddress(builder, address); Theater.addMobile(builder, 12233345); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Name: " + theater.name()); System.out.println("Address: " + theater.address()); System.out.println("Mobile: " + theater.mobile()); // 更新 mobile theater.mutateMobile(22333341); // 我们可以再次编写 theater 对象以将其进一步发送 // read the updated mobile value System.out.println("Updated Mobile: " + theater.mobile()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 76
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California Mobile: 12233345 Updated Mobile: 22333341
Flat Buffers - 语言独立性
概述
到目前为止,我们一直使用 Java 来序列化和反序列化电影院数据。但是,Google Flat 缓冲区提供的关键功能之一是"语言独立性"。在本章中,我们将了解如何使用 Java 进行序列化并使用 Python 进行反序列化。
继续使用Flat Buffers - String一章中的Theater 示例,以下是我们在本示例中使用的模式 −
theater.fbs
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; } root_type Theater;
使用 Java 进行序列化
要使用 Flat Buffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在当前目录的 com > tutorialspoint > theater 文件夹中创建一个 Theater.java 类。我们在应用程序中使用此类的方式类似于 Flat Buffers - Schema 一章中所做的那样。
使用从 fbs 文件创建的 Java 类
首先让我们创建一个 writer 来写入 theater 信息−
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); int name = builder.createString("Silver Screener"); int address = builder.createString("212, Maple Street, LA, California"); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // add the name and address to the Theater FlatBuffer Theater.addName(builder, name); Theater.addAddress(builder, address); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 72
使用 Python 反序列化序列化对象
从 proto 文件生成 Python 类
让我们为 Theater 类生成 Python 代码 −
flatc --python theater.fbs
执行此命令后,您会注意到当前目录中的 com > tutorialspoint > theater 文件夹中有一个自动生成的类 Theater.py。此类将帮助我们反序列化 Theater 对象。
使用生成的 Python 类
现在,让我们编写数据读取器,它将使用 java 读取包含序列化对象的文件。 −
theaterReader.py
import Theater filename = "E:/theater_flatbuffers_output"; print("Reading from file: " + filename) theater = Theater.Theater() f = open(filename, "rb") buf = f.read() buf = bytearray(buf) theater = theater.GetRootAs(buf); f.close() print("Name: " + theater.Name().decode("utf-8")) print("Address: " + theater.Address().decode("utf-8"))
然后,让我们执行阅读器。
py theaterReader.py Reading from file: E:/theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California
因此,正如我们所见,Java 客户端写入的所有值都被我们的 Python 客户端正确地反序列化和读取,这实际上意味着 Flat Buffers 与语言无关。
Flat Buffers - 向后兼容性
概述
FlatBuffers 模式向后兼容。这意味着,如果我们稍后将属性添加到 flatbuffers 模式,现有代码仍然可以工作。这在维护旧代码库时非常有用。考虑一个 Theater Schema 仅包含名称和地址的场景,如下所示:
theater.fbs
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; } root_type Theater;
如果我们为该模式生成代码,它将支持将名称和地址存储在 flatbuffer bin 文件中。
现在随着时间的推移,我们需要向模式添加手机号码,然后我们需要再次生成更新的代码。因此,我们还需要更新写入器和读取器代码。但在生产中,通常直接更改代码并不容易,并且进行这样的更改可能会破坏整个系统。这里的Flat Buffers可确保旧的读取器代码仍可与基于新模式生成的 flatbuffers bin 文件正常工作,而无需进行任何更改。
从 fbs 文件创建 Java 类
要使用Flat Buffers,我们现在必须使用 flatc 二进制文件从此".fbs"文件创建所需的类。让我们看看如何做到这一点 −
flatc --java theater.fbs
这将在 com > 中创建一个 Theater.java 类tutorialspoint > theater 文件夹。我们在应用程序中使用此类的方式与 Flat Buffers - Schema 一章中的方式类似。
使用从 fbs 文件创建的 Java 类
首先让我们创建一个 writer 来写入 theater 信息−
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); int name = builder.createString("Silver Screener"); int address = builder.createString("212, Maple Street, LA, California"); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // add the name and address to the Theater FlatBuffer Theater.addName(builder, name); Theater.addAddress(builder, address); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
接下来,我们将有一个阅读器来读取Theater 信息 −
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Name: " + theater.name()); System.out.println("Address: " + theater.address()); } } }
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 72
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California
向后兼容性测试
现在让我们向架构添加一个手机号码,更新写入器并在不更新它的情况下运行读取器以检查向后兼容性。
theater.fbs
namespace com.tutorialspoint.theater; table Theater { name:string; address:string; mobile:int; } root_type Theater;
从 fbs 文件创建 Java 类
使用 flatc 二进制文件从此".fbs"文件创建所需的类。
flatc --java theater.fbs
使用从 fbs 文件创建的 Java 类
首先让我们创建一个 writer 来写入 theater 信息−
TheaterWriter.java
package com.tutorialspoint.theater; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import com.google.flatbuffers.FlatBufferBuilder; public class TheaterWriter { public static void main(String[] args) throws FileNotFoundException, IOException { // 创建一个Flat Buffers构建器 // 它将用于创建Theater FlatBuffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); int name = builder.createString("Silver Screener"); int address = builder.createString("212, Maple Street, LA, California"); // 使用 startTheater() 方法创建Theater FlatBuffers Theater.startTheater(builder); // 将姓名、地址和手机添加到 Theater FlatBuffer Theater.addName(builder, name); Theater.addAddress(builder, address); Theater.addMobile(builder, 12233345); // 标记在 Gret FlatBuffer 中输入数据的结束 int theater = Theater.endTheater(builder); // 完成构建器 builder.finish(theater); // 获取要存储的字节 byte[] data = builder.sizedByteArray(); String filename = "theater_flatbuffers_output"; System.out.println("Saving theater to file: " + filename); // 将构建器内容写入名为 theater_flatbuffers_output 的文件 try(FileOutputStream output = new FileOutputStream(filename)){ output.write(data); } System.out.println("Saved theater with following data to disk: " + theater); } }
编译项目
现在我们已经设置了编写器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们首先执行 writer −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater to file: theater_flatbuffers_output Saved theater with following data to disk: 76
使用旧读取器反序列化序列化对象
现在,让我们执行读取器来读取同一文件 −
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California
更新 Reader 并再次反序列化
TheaterReader.java
package com.tutorialspoint.theater; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.ByteBuffer; public class TheaterReader { public static void main(String[] args) throws FileNotFoundException, IOException { String filename = "theater_flatbuffers_output"; System.out.println("Reading from file " + filename); try(FileInputStream input = new FileInputStream(filename)) { // 获取序列化数据 byte[] data = input.readAllBytes(); ByteBuffer buf = ByteBuffer.wrap(data); // 读取序列化数据中的根对象 Theater theater = Theater.getRootAsTheater(buf); // 打印 theater 剧场值 System.out.println("Name: " + theater.name()); System.out.println("Address: " + theater.address()); System.out.println("Mobile: " + theater.mobile()); } } }
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
反序列化序列化对象
现在,让我们执行读取器来读取同一个文件−
java -cp . arget\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California Mobile: 12233345