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);
        
        // 标记 Greet FlatBuffer 中输入数据的结束
        int Greeting = Greet.endGreet(builder);
        
        // 完成构建器
        builder.finish(greet);
        
        // 获取要存储的字节
        byte[] data = builder.sizedByteArray();
        
        String filename = "greeting_flatbuffers_output";
        System.out.println("将问候语保存到文件:" + filename);
        // 将构建器内容写入名为 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 只是从同一个文件中读取数据,对其进行反序列化,然后打印有关问候语的数据。

编译项目

现在我们已经设置了 readerwriter,让我们编译项目。

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正确地反序列化并相应地打印出来。