- FlatBuffers 教程
- FlatBuffers - 首页
- FlatBuffers - 简介
- FlatBuffers - Schema
- FlatBuffers - 结构
- FlatBuffers - 表
- FlatBuffers - 字符串
- FlatBuffers - 数字
- FlatBuffers - 布尔值
- FlatBuffers - 枚举
- FlatBuffers - 向量
- FlatBuffers - 结构体
- FlatBuffers - 联合体
- FlatBuffers - 嵌套表
- FlatBuffers - 默认值
- FlatBuffers - JSON 转二进制
- FlatBuffers - 二进制转 JSON
- FlatBuffers - 可变缓冲区
- FlatBuffers - 向后兼容性
- FlatBuffers - 语言无关性
- FlatBuffers 有用资源
- FlatBuffers 快速指南
- FlatBuffers - 有用资源
- FlatBuffers - 讨论
FlatBuffers 快速指南
FlatBuffers - 简介
在深入了解 FlatBuffers 之前,让我们先简要回顾一下序列化,这是 FlatBuffers 所做的工作。
什么是序列化和反序列化?
每当我们需要将对象状态持久化到内存系统时,都需要序列化。在序列化中,我们将对象转换为字节,并将这些字节存储在内存系统中。这些存储的字节随后可以被反序列化以恢复对象状态。由于我们将对象转换为字节,因此可以将其存储在任何地方,包括文件系统、消息队列、数据库等等,然后我们可以将这些字节传输到不同的机器并检索对象状态。
为什么我们需要序列化和反序列化?
序列化有助于持久化对象状态,然后我们可以将其传输到网络上的任何位置。接收后,我们可以反序列化对象,或者换句话说,我们可以随时在不同的机器上从字节恢复我们的对象。这是序列化和反序列化的许多重要用例之一。另一个重要用例是对象需要通过网络传输的情况。消息队列、数据库对象、REST API 都遵循此原则。在这种情况下,发送方首先序列化对象,然后将其传输到接收方。接收方然后反序列化已序列化的对象。
在 REST API、微服务架构中,应用程序通常被分解成小的服务,这些服务通过消息队列和 API 相互通信。由于通信是通过网络进行的,需要频繁地将对象转换为字节,然后再转换回对象。因此,序列化和反序列化在分布式环境中变得非常关键。
为什么选择 FlatBuffers?
Google FlatBuffers 执行将对象序列化和反序列化为字节的操作,这些字节可以跨网络传输。但也有一些其他的库和机制可以传输数据。
那么,是什么让 FlatBuffers 如此特别呢?以下是一些重要的特性:
语言无关性 - FlatBuffers 编译器可以为多种语言创建代码,例如 Java、Python、Go、C、C++ 等。因此,Java 对象可以由 Java 程序序列化为字节,并且可以反序列化为 Python 对象,反之亦然。
高效的数据压缩 - FlatBuffers API 最初是为游戏环境和性能关键型系统开发的,其设计考虑了数据压缩和性能。它非常节省内存,甚至比 Google Protocol Buffers(另一个 Google 序列化和反序列化库)更快。
向前和向后兼容性 - FlatBuffers 架构同时具有向前和向后兼容性。FlatBuffers 的 schema 支持在较新代码中添加更改,并允许弃用较旧的更改,而不会破坏向后兼容性。
易于使用 - FlatBuffers 库自动生成序列化代码(我们将在接下来的章节中看到),具有版本控制方案,以确保数据创建者和数据使用者可以拥有序列化定义的不同版本等。
JSON 可转换 FlatBuffers schema 文件可以转换为 JSON 文件,同样,我们可以使用 FlatBuffers schema 转换 JSON 文件。
FlatBuffers 与其他方案对比 (XML/JSON/Java 序列化)
让我们看看其他通过网络传输数据的方式与 FlatBuffers 相比如何。
| 特性 | FlatBuffers | JSON | XML |
|---|---|---|---|
| 语言无关性 | 是 | 是 | 是 |
| 序列化数据大小 | 三者中最小的 | 小于 XML | 三者中最大的 |
| 人类可读性 | 否,因为它使用单独的编码 schema | 是,因为它使用基于文本的格式 | 是,因为它使用基于文本的格式 |
| 序列化速度 | 三者中最快 | 快于 XML | 三者中最慢 |
| 数据类型支持 | 比其他两者更丰富。支持复杂数据类型,如 Any、oneof 等。 | 支持基本数据类型 | 支持基本数据类型 |
| 对演变 schema 的支持 | 是 | 否 | 否 |
FlatBuffers - Schema
概述
现在让我们使用 Google FlatBuffers 并看看它如何与一个简单的问候应用程序一起工作。在这个例子中,我们将创建一个简单的应用程序,它将执行以下操作:
问候写入器
从用户处获取问候语和用户名
将上述信息存储在磁盘上的文件中
问候读取器
读取我们在上面存储的文件
将数据转换为对象并打印数据
FlatBuffers Schema 文件
FlatBuffers 的“schema 文件”包含我们要序列化的数据的 schema 定义。数据存储在具有扩展名“.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 告诉 FlatBuffers 编译器根表是 Greet,它将是生成代码时的主类。
FlatBuffers 代码生成
现在我们已经定义了,让我们安装“flatc”二进制文件,我们将使用它来自动生成上述Greet类的代码。二进制文件可以在"https://github.com/google/flatbuffers/releases"找到。
根据操作系统选择正确的二进制文件。我们将在 Windows 上安装 FlatBuffers 编译器二进制文件,但 Linux 的步骤差别不大。
我们已下载https://github.com/google/flatbuffers/releases/download/v24.3.25/Windows.flatc.binary.zip
验证 FlatBuffers 编译器设置
安装后,确保您可以通过命令行访问它:
flatc --version flatc version 24.3.25
这确认 Flatc 已正确安装。现在让我们继续为 Java 创建上面描述的问候应用程序。
Java 中的问候应用程序
现在我们已经安装了flatc,我们可以使用flatc从 .fbs 文件自动生成代码。让我们首先创建一个 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 > greeting文件夹下看到一个自动生成的类。
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 {
// create a flat buffer builder
// it will be used to create Greet FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// read greeting and username from console
int greeting = builder.createString(args[0]);
int username = builder.createString(args[1]);
// create Greet FlatBuffers using startGreet() method
Greet.startGreet(builder);
// add the greeting and username to the Greet FlatBuffer
Greet.addGreeting(builder, greeting);
Greet.addUsername(builder, username);
// mark end of data being entered in Greet FlatBuffer
int greet = Greet.endGreet(builder);
// finish the builder
builder.finish(greet);
// get the bytes to be stored
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: \n" + greeting);
}
}
该写入器简单地获取 CLI 参数,创建Greet对象,将其序列化,然后将其转储到文件中。
现在让我们编写一个读取器来读取文件:
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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Greet greet = Greet.getRootAsGreet(buf);
// print greet values
System.out.println("Greeting: " + greet.greeting() + "\n" + "Username: " + greet.username());
}
}
}
该读取器简单地从同一文件中读取,将其反序列化,并打印问候信息。
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,让我们首先执行写入器将对象序列化到文件系统。
java -cp .\target\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 .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.greeting.GreetReader Reading from file greeting_protobuf_output Greeting: Hello Username: John
因此,正如我们看到的,写入器序列化并保存到文件的数据,被读取器正确地反序列化并相应地打印出来。
FlatBuffers - 结构
概述
现在让我们看看 Google FlatBuffers 提供的一些基本数据结构和数据类型。我们将使用电影院的例子来查看这些数据结构。
请注意,对于此结构,虽然我们将使用 Java 代码,但在 Python 代码中使用它们也应该同样简单且可行。
在接下来的几章中,我们将逐一讨论以下 FlatBuffers 数据类型:
数据类型
表 (table) - “表”是 FlatBuffers 的一个非常基本的基础构件。它在我们使用的语言(例如 Java、Python 等)中转换为类
字符串 (string) - “字符串”数据类型在我们使用的语言(例如 Java、Python 等)中转换为字符串
数字 (Numbers) - 数字包括 FlatBuffers 类型,如 int、short、float、double,它们是 Protobuf 的基本构建块。它在我们使用的语言(例如 Java、Python 等)中分别转换为 int、long、float、double。我们也可以使用别名,如 int16 代表 short,float32 代表 float 等。
布尔值 (bool) - “布尔值”数据类型是 FlatBuffers 的基本构建块之一。它在我们使用的语言(例如 Java、Python 等)中转换为布尔值。
枚举 (enum) − “enum” 是 FlatBuffers 的复合数据类型之一。它在我们使用的语言中被翻译成枚举,例如 Java。
向量 (vector) − 使用 [] 符号创建向量或数组,它是 FlatBuffers 的复合数据类型之一。FlatBuffers 向量类似于 Java 数组。
结构体 (struct) − “struct” 是 FlatBuffers 的复合数据类型之一。它用于创建不可修改的标量值集合。struct 使用更少的内存,并且查找速度非常快。
嵌套类 − 我们可以将使用 "table" 创建的类嵌套在另一个 "table" 中,从而创建嵌套类。
联合体 (union) − “union” 用于创建一个可以接受任何不同类型值的结构。
FlatBuffers - 表
概述
FlatBuffers 的最基本构建块是表 (table) 属性。这相当于我们在使用的语言中的类 (class),例如 Java、Python 等。
示例代码
以下是我们需要使用的语法,用于指示 FlatBuffers 我们将创建给定表的实例:
namespace com.tutorialspoint.theater;
table Theater {
}
root_type Theater;
我们将以上内容保存到“theater.fbs”中,并在我们探索其他数据结构时使用它。
解释
namespace com.tutorialspoint.theater;
此参数特定于 Java,即“.fbs”文件生成的代码所在的包。Theater 类将创建在com.tutorialpoint.theater包中。
接下来,我们创建一个表 Theater:
table Theater
这只不过是将要创建/重新创建的对象的基类的类名。请注意,它在当前形式下是无用的,因为它没有任何其他属性。但是,随着我们的推进,我们将添加更多属性。
使用多个 table 属性
单个 fbs 文件也可以包含多个表。例如,如果需要,我们可以在同一个文件中添加一个Visitor表。FlatBuffers 将确保 Theater 类使用 root_type 属性保持为主类。例如:
namespace com.tutorialspoint.theater;
table Theater {
}
table Visitor {
}
root_type Theater;
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用flatc二进制文件从这个“.fbs”文件创建所需的类。让我们看看如何做到这一点:
flat --java theater.fbs
使用从 fbs 文件创建的 Java 类
就是这样!以上命令应该在当前目录中创建所需的文件,现在我们可以在 Java 代码中使用它们:
// Create a FlatBuffer Builder with default buffer FlatBufferBuilder builder = new FlatBufferBuilder(1024); // Create Theater FlatBuffers using startTheater() method Theater.startTheater(builder);
在这个阶段,它不是很有用,因为我们还没有向表中添加任何属性。当我们在Flat Buffers - string章节中查看字符串时,我们将进行此操作。
FlatBuffers - 字符串
概述
FlatBuffers 字符串在我们使用的语言中被翻译成字符串,例如 Java、Python 等。继续theater示例,以下是我们需要使用的语法,用于指示 FlatBuffers 我们将创建一个字符串:
theater.fbs
namespace com.tutorialspoint.theater;
table Theater {
name:string;
address:string;
}
root_type Theater;
现在我们的表包含两个字符串属性。每个属性的默认值为 null。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
int name = builder.createString("Silver Screener");
int address = builder.createString("212, Maple Street, LA, California");
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add the name and address to the Theater FlatBuffer
Theater.addName(builder, name);
Theater.addAddress(builder, address);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Name: " + theater.name() + "\n" + "Address: " + theater.address());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\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中,我们将了解数字。
FlatBuffers - 数字
概述
数字包括 flatbuffers 类型,如int、short、float、double,它们是 FlatBuffers 的基本构建块。它们分别在我们使用的语言中被翻译成int、short、float、double,例如 Java、Python 等。
继续我们来自Flat Buffers - String章节的theater示例,以下是我们需要使用的语法,用于指示 FlatBuffers 我们将创建数字:
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 类
要使用 FlatBuffers,我们现在必须使用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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
int totalCapacity = 320;
long mobile = 98234567189L;
float baseTicketPrice = 22.45f;
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addTotalCapcity(builder, totalCapacity);
Theater.addMobile(builder, mobile);
Theater.addBaseTicketPrice(builder, baseTicketPrice);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Total Capacity: " + theater.totalCapcity()
+ "\n" + "Mobile: " + theater.mobile()
+ "\n" + "Base Ticket Price: " + theater.baseTicketPrice());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\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中,我们将了解数字。
FlatBuffers - 布尔值
概述
bool数据类型是 FlatBuffers 的基本构建块之一。它在我们使用的语言中被翻译成Boolean,例如Java、Python等。
继续我们来自Flat Buffers - String章节的theater示例,以下是我们需要使用的语法,用于指示 FlatBuffers 我们将创建bool:
theater.fbs
namespace com.tutorialspoint.theater;
table Theater {
drive_in:bool;
}
root_type Theater;
现在我们的表包含一个bool属性。默认值为 false。
从 FBS 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
boolean driveIn = true;
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addDriveIn(builder, driveIn);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Drive In: " + theater.driveIn());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Drive In: true
因此,正如我们所看到的,我们能够通过将二进制数据反序列化为Theater对象来读取序列化后的字符串。在下一章Flat Buffers - Enum中,我们将了解数字。
FlatBuffers - 枚举 (enum)
概述
枚举 (enum)数据类型是 FlatBuffers 的复合数据类型之一。它相当于在我们使用的语言中的枚举 (enum),例如Java等。
继续我们来自Flat Buffers - String章节的theater示例,以下是我们需要使用的语法,用于指示 FlatBuffers 我们将创建一个枚举 (enum):
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;
现在我们的表包含一个枚举 (enum)属性。我们为每个枚举常量分配了一个值,除了 DEBIT_CARD,它默认取增量值 2。
我们定义了枚举 (enum),并在下面将其用作数据类型以及“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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addPayment(builder, PAYMENT_SYSTEM.DEBIT_CARD);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Payment Method: " + theater.payment());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器 (writer):
> java -cp .\target\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 .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Payment Method: 2
因此,正如我们所看到的,我们能够通过将二进制数据反序列化为Theater对象来读取序列化后的枚举 (enum)。在下一章Protocol Buffers - Vector中,我们将了解向量,一种复合类型。
FlatBuffers - 向量
概述
向量 (Vector)数据类型是 FlatBuffers 的复合数据类型之一。它相当于在我们使用的语言中的数组 (array)或列表 (List),例如Java等。
继续我们来自Flat Buffers - String章节的theater示例,以下是我们需要使用的语法,用于指示 FlatBuffers 我们将创建一个向量 (vector):
theater.fbs
namespace com.tutorialspoint.theater;
table Theater {
snacks:[string]; // vector of strings
tickets:[float]; // vector of floats
}
root_type Theater;
现在我们的表包含字符串和浮点数的向量 (vector)属性。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用flatc二进制文件从这个“.fbs”文件创建所需的类。让我们看看如何做到这一点:
flatc --java theater.fbs
这将在当前目录中的com > tutorialspoint > theater文件夹中创建一个 Theater.java 类。我们像在Flat Buffers - Schema章节中所做的那样,在我们的应用程序中使用此类。
使用从 fbs 文件创建的 Java 类
创建和写入向量
为了创建一个向量,我们需要首先准备标量类型数组的偏移量,然后我们可以将向量添加到 flat buffer 中。
// create data for an array of strings
int popcorn = builder.createString("Popcorn");
int coke = builder.createString("Coke");
int chips = builder.createString("Chips");
int soda = builder.createString("Soda");
// create array for snacks
int[] snacks = {popcorn, coke, chips, soda};
// create offset for snacks vector
int snacksVector = Theater.createSnacksVector(builder, snacks);
// add details to the 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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create data for an array of strings
int popcorn = builder.createString("Popcorn");
int coke = builder.createString("Coke");
int chips = builder.createString("Chips");
int soda = builder.createString("Soda");
// create array for snacks
int[] snacks = {popcorn, coke, chips, soda};
// create array for tickets
float[] tickets = {100.0f, 100.f, 200.f};
// create offset for snacks vector
int snacksVector = Theater.createSnacksVector(builder, snacks);
// create offset for tickets vector
int ticketsVector = Theater.createTicketsVector(builder, tickets);
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addSnacks(builder, snacksVector);
Theater.addTickets(builder, ticketsVector);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
读取向量
为了读取向量,我们有方法来获取向量的长度并通过索引获取条目,如下所示。
// iterate snacks vector of length determined by snacksLength() method
for(int i = 0; i < theater.snacksLength(); i++ ) {
// get a snack by its index
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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Snacks: ");
for(int i = 0; i < theater.snacksLength(); i++ ) {
System.out.print(" " + theater.snacks(i));
}
System.out.println("\nTickets: ");
for(int i = 0; i < theater.ticketsLength(); i++ ) {
System.out.print(" " + theater.tickets(i));
}
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器 (writer):
> java -cp .\target\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 .\target\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中,我们将了解结构体,一种复合类型。
FlatBuffers - 结构体 (struct)
概述
结构体 (struct)数据类型是 FlatBuffers 的复合数据类型之一。它用于创建不可变的数据结构。结构体占用更少的内存,查找速度很快。结构体通常是标量类型的组合。
继续我们来自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;
现在我们的表包含定义为 Position 类型的 location 属性。Position 是一个结构体,用于定义三个整数的数据结构。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用flatc二进制文件从这个“.fbs”文件创建所需的类。让我们看看如何做到这一点:
flatc --java theater.fbs
这将在当前目录中的com > tutorialspoint > theater文件夹中创建Theater和Position类。我们像在Flat Buffers - Schema章节中所做的那样,在我们的应用程序中使用此类。
使用从 fbs 文件创建的 Java 类
创建和写入结构体
为了创建一个结构体,我们需要首先准备标量类型数组的偏移量,然后我们可以将向量添加到 flat buffer 中。
// create offset for location struct int location = Position.createPosition(builder, 100, 110, 120); // add details to the Theater FlatBuffer Theater.addLocation(builder, location);
以下示例代码展示了创建整数结构体的过程。
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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create offset for location struct
int location = Position.createPosition(builder, 100, 110, 120);
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addLocation(builder, location);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
读取结构体
为了读取结构体,我们有方法来获取结构体的每个值。
Position position = theater.location();
System.out.println("x: " + position.x());
System.out.println("y: " + position.y());
System.out.println("z: " + position.z());
以下示例代码展示了读取整数结构体的过程。
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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
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());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器 (writer):
> java -cp .\target\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 .\target\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中,我们将了解联合体,一种复合类型。
FlatBuffers - 联合体 (union)
概述
联合体 (union)数据类型是 FlatBuffers 的复合数据类型之一。它用于创建灵活的数据结构,可以采用任何所需类型。
继续我们来自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 属性。在 Theater 表中,我们定义了联合类型的 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 类
创建和写入联合体
为了创建一个联合体,我们需要首先准备所需类型的偏移量,例如 Viewer,然后我们可以将 Viewer 与其类型一起添加到 flat buffer 中。
// create offset for Viewer
int viewerName = builder.createString("Mery");
int viewerAddress = builder.createString("Avenue 4");
int viewer = Viewer.createViewer(builder, viewerName, viewerAddress);
//add union tyoe
Theater.addPeopleType(builder, People.Viewer);
// add details to the Theater FlatBuffer
Theater.addPeople(builder, viewer);
以下示例代码展示了创建联合体的过程。
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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create offset for Viewer
int viewerName = builder.createString("Mery");
int viewerAddress = builder.createString("Avenue 4");
int viewer = Viewer.createViewer(builder, viewerName, viewerAddress);
// create offset for vector
//int people = Theater.createPeople
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
//add union type
Theater.addPeopleType(builder, People.Viewer);
// add details to the Theater FlatBuffer
Theater.addPeople(builder, viewer);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
读取联合体
为了读取一个联合体(Union),我们可以检查联合体对象的类型,然后相应地检索值。
// get the saved union type
int unionType = theater.peopleType();
// if union is of type Viewer
if(unionType == People.Viewer) {
Viewer viewer = (Viewer)theater.people(new Viewer());
System.out.println("Name: " + viewer.name());
System.out.println("Address: " + viewer.address());
}
// if union is of type 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());
}
下面的示例代码展示了读取联合体的过程。
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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("People: ");
// get the type of union
int unionType = theater.peopleType();
// if union is of Viewer type
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());
}
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器 (writer):
> java -cp .\target\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 .\target\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 - 嵌套表中,我们将了解复合类型嵌套表。
FlatBuffers - 嵌套表
概述
在这里,我们将学习如何在 Flat Buffers 中创建嵌套表。它相当于一个嵌套的**Java**类。
继续我们从Flat Buffers - 字符串章节中的**theater**示例,以下是我们需要使用的语法,以便指示 FlatBuffers 我们将创建一个**嵌套表**:
theater.fbs
namespace com.tutorialspoint.theater;
table Theater {
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 类。我们在应用程序中使用此类,与Flat Buffers - 模式章节中所做的一样。
使用从 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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create offset for TheaterOwner
int ownerName = builder.createString("Mery");
int ownerAddress = builder.createString("Avenue 4");
int owner = TheaterOwner.createTheaterOwner(builder, ownerName, ownerAddress);
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addOwner(builder, owner);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Owner Details: ");
TheaterOwner owner = theater.owner();
System.out.println("Name: " + owner.name());
System.out.println("Address: " + owner.address());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Owner Details: Name: Mery Address: Avenue 4
因此,正如我们所看到的,我们能够通过将二进制数据反序列化为**Theater**对象来读取序列化的嵌套表/对象。
FlatBuffers - 默认值
概述
我们在之前的示例中已经看到了如何在 Flat Buffers 中序列化和反序列化各种类型。如果我们没有指定任何值,则会存储默认值。如果我们为变量指定相同的默认值,则 FlatBuffers 不会分配额外的空间。
Flat Buffers 支持其数据类型的默认值,如下表所示:
| 数据类型 | 默认值 |
|---|---|
| int16 / short / int / long | 0 |
| Float/double | 0.0 |
| 字符串 | 空字符串 |
| 布尔值 | False |
| 枚举 | 第一个枚举项,即“index=0”的项 |
| 向量 | 空列表 |
| 嵌套类 | null |
因此,如果用户没有为这些数据类型指定数据,则它们将采用上述默认值。现在,让我们继续我们的**theater**示例来演示它的工作原理。
在这个示例中,我们将让所有字段都使用默认值。唯一指定的字段将是剧院的名称。
继续我们从Flat Buffers - 字符串章节中的**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 - 模式章节中所做的一样。
使用从 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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create offset for name
int name = builder.createString("Mery");
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addName(builder, name);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
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);
}
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\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**对象来读取默认值。
FlatBuffers - JSON 转二进制
概述
JSON 是一种非常流行的网络数据传输格式。为了提供 JSON 兼容性,Flat Buffers 编译器 flatc 可以将源 JSON 转换为 Flat Buffer 二进制格式,然后可以使用该格式反序列化最初由 JSON 表示的对象。
考虑以下包含 Theater 对象信息的 JSON
theater.json
{
"name" : "Silver Screener",
"address" : "212, Maple Street, LA, California",
"mobile": 12322224
}
theater.fbs
这是我们的 Flat Buffers 模式文件
namespace com.tutorialspoint.theater;
table Theater {
name:string;
address:string;
mobile:int;
}
root_type Theater;
现在让我们首先使用以下命令获取 json(**theater.json**)的 Flat Buffer 二进制表示形式,根据我们的模式(**theater.fbs**):
flatc --binary theater.fbs theater.json
它将在当前文件夹中创建 theater.bin,我们可以读取它来反序列化 Theater 对象。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用flatc二进制文件从这个“.fbs”文件创建所需的类。让我们看看如何做到这一点:
flatc --java theater.fbs
这将在当前目录的**com > tutorialspoint > theater**文件夹中创建一个 Theater 类。我们在应用程序中使用此类,与Flat Buffers - 模式章节中所做的一样。
使用从 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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Name: " + theater.name());
System.out.println("Address: " + theater.address());
System.out.println("Mobile: " + theater.mobile());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
反序列化已序列化的对象
现在,让我们执行读取器从同一个文件读取:
java -cp .\target\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**对象来读取默认值。
FlatBuffers - 二进制转 JSON
概述
JSON 是一种非常流行的网络数据传输格式。为了提供 JSON 兼容性,Flat Buffers 编译器 flatc 可以将源 JSON 转换为 Flat Buffer 二进制格式,然后可以使用该格式反序列化最初由 JSON 表示的对象。我们在之前的章节Flat Buffers - JSON 转二进制中已经演练过这个过程。现在我们将执行反向操作,从 Flat Buffers 二进制文件中检索 JSON。
考虑在之前的章节Flat Buffers - JSON 转二进制中创建的 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
}
现在让我们首先使用以下命令获取 json(**theater.json**)的 Flat Buffer 二进制表示形式,根据我们的模式(**theater.fbs**):
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 提供的具有常量访问器的类来读取此文件。这有助于在多个读取器中使用 Flat Buffer 文件时保持一致性。但有时,我们可能需要在读取后修改一个值,并需要将修改后的值传递给下一个读取器。我们可以通过从头开始创建一个新的 Flat Buffers 来实现这一点,这对于大型更改来说更好,更高效。对于小型更改,Flat Buffers 提供了一个选项**--gen-mutable**到**flatc**编译器
以生成非常量访问器来修改 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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
// create offset for name and address
int name = builder.createString("Silver Screener");
int address = builder.createString("212, Maple Street, LA, California");
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add details to the Theater FlatBuffer
Theater.addName(builder, name);
Theater.addAddress(builder, address);
Theater.addMobile(builder, 12233345);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Name: " + theater.name());
System.out.println("Address: " + theater.address());
System.out.println("Mobile: " + theater.mobile());
// Update mobile
theater.mutateMobile(22333341);
// we can write the theater object again to send it further
// read the updated mobile value
System.out.println("Updated Mobile: " + theater.mobile());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\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
FlatBuffers - 语言无关性
概述
到目前为止,我们一直在使用 Java 来序列化和反序列化电影院数据。但是,Google Flat Buffers 提供的一个关键特性是**“语言无关性”**。在本节中,我们将学习如何使用 Java 序列化,并使用 Python 反序列化。
继续我们从Flat Buffers - 字符串章节中的**theater**示例,以下是我们在本例中使用的模式:
theater.fbs
namespace com.tutorialspoint.theater;
table Theater {
name:string;
address:string;
}
root_type Theater;
使用 Java 序列化
要使用 FlatBuffers,我们现在必须使用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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
int name = builder.createString("Silver Screener");
int address = builder.createString("212, Maple Street, LA, California");
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add the name and address to the Theater FlatBuffer
Theater.addName(builder, name);
Theater.addAddress(builder, address);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 是语言无关的。
FlatBuffers - 向后兼容性
概述
FlatBuffers 模式是向后兼容的。这意味着,如果我们稍后更改、添加或删除 FlatBuffers 模式的属性,现有的代码仍然可以工作。这在维护遗留代码库时非常有用。考虑一种情况,其中 Theater 模式仅包含名称和地址,如下所示
theater.fbs
namespace com.tutorialspoint.theater;
table Theater {
name:string;
address:string;
}
root_type Theater;
如果我们为此模式生成代码,它将支持在 FlatBuffer bin 文件中存储名称和地址。
现在随着时间的推移,我们需要向模式添加一个手机号码,然后我们需要再次生成更新的代码。结果,我们还需要更新写入器和读取器代码。但在生产环境中,通常直接更改代码并不容易,并且进行此类更改可能会破坏整个系统。Flat Buffers 在这里确保旧的读取器代码仍然可以与新的模式生成的 FlatBuffers bin 文件一起正常工作,无需更改。
从 fbs 文件创建 Java 类
要使用 FlatBuffers,我们现在必须使用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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
int name = builder.createString("Silver Screener");
int address = builder.createString("212, Maple Street, LA, California");
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add the name and address to the Theater FlatBuffer
Theater.addName(builder, name);
Theater.addAddress(builder, address);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
接下来,我们将有一个读取器 (reader)来读取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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Name: " + theater.name());
System.out.println("Address: " + theater.address());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\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 {
// create a flat buffer builder
// it will be used to create Theater FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
int name = builder.createString("Silver Screener");
int address = builder.createString("212, Maple Street, LA, California");
// create theater FlatBuffers using startTheater() method
Theater.startTheater(builder);
// add the name, address and mobile to the Theater FlatBuffer
Theater.addName(builder, name);
Theater.addAddress(builder, address);
Theater.addMobile(builder, 12233345);
// mark end of data being entered in Greet FlatBuffer
int theater = Theater.endTheater(builder);
// finish the builder
builder.finish(theater);
// get the bytes to be stored
byte[] data = builder.sizedByteArray();
String filename = "theater_flatbuffers_output";
System.out.println("Saving theater to file: " + filename);
// write the builder content to the file named theater_flatbuffers_output
try(FileOutputStream output = new FileOutputStream(filename)){
output.write(data);
}
System.out.println("Saved theater with following data to disk: \n" + theater);
}
}
编译项目
现在我们已经设置了**写入器**,让我们编译项目。
mvn clean install
序列化 Java 对象
现在,编译后,让我们先执行写入器:
java -cp .\target\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 .\target\flatbuffers-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader Reading from file theater_flatbuffers_output Name: Silver Screener Address: 212, Maple Street, LA, California
更新读取器并再次反序列化
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)) {
// get the serialized data
byte[] data = input.readAllBytes();
ByteBuffer buf = ByteBuffer.wrap(data);
// read the root object in serialized data
Theater theater = Theater.getRootAsTheater(buf);
// print theater values
System.out.println("Name: " + theater.name());
System.out.println("Address: " + theater.address());
System.out.println("Mobile: " + theater.mobile());
}
}
}
编译项目
现在我们已经设置了读取器和写入器,让我们编译项目。
mvn clean install
反序列化已序列化的对象
现在,让我们执行读取器从同一个文件读取:
java -cp .\target\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