- Protocol Buffers 教程
- Protocol Buffers - 首頁
- Protocol Buffers - 簡介
- Protocol Buffers - 基本應用
- Protocol Buffers - 結構
- Protocol Buffers - 訊息
- Protocol Buffers - 字串
- Protocol Buffers - 數字
- Protocol Buffers - 布林值
- Protocol Buffers - 列舉
- Protocol Buffers - 重複欄位
- Protocol Buffers - 對映
- Protocol Buffers - 巢狀類
- Protocol Buffers - 可選欄位和預設值
- Protocol Buffers - 語言無關性
- Protocol Buffers - 複合資料型別
- Protocol Buffers - 命令列使用
- Protocol Buffers - 更新定義規則
- Protocol Buffers - 與 Kafka 整合
- Protocol Buffers - 在其他語言中的使用
- Protocol Buffers 有用資源
- Protocol Buffers - 快速指南
- Protocol Buffers - 有用資源
- Protocol Buffers - 討論
Protocol Buffers - 基本應用
概述
現在讓我們使用 Google Protocol Buffer,看看它如何與簡單的問候應用一起工作。在這個例子中,我們將建立一個簡單的應用程式,它將執行以下操作:
問候編寫者:
從使用者處獲取問候語和使用者名稱
將上述資訊儲存到磁碟上的檔案中
問候讀取者:
讀取我們在上面儲存的同一檔案
將資料轉換為物件並列印資料
Protocol Buffer 定義檔案
Protocol Buffer 的“定義檔案”包含我們想要序列化的資料的模式定義。資料儲存在一個人類可讀的檔案中,副檔名為 **".proto"**。
讓我們將以下資料儲存在 **greeting.proto** 中,我們將在我們的第一個應用程式中使用它。
syntax = "proto3";
package tutorialspoint;
option java_package = "com.tutorialspoint.greeting";
message Greet {
string greeting = 1;
string username = 2;
}
理解每個結構
現在,讓我們仔細看看資料,並瞭解上面程式碼塊中每一行程式碼的作用。
syntax = "proto3";
這裡的 **syntax** 表示我們正在使用哪個版本的 Protobuf。因此,我們使用的是最新版本 3,因此模式可以使用所有對版本 3 有效的語法。
package tutorialspoint;
這裡的 **package** 用於衝突解決,例如,如果我們有多個同名的類/成員。
option java_package = "com.tutorialspoint.greeting";
此引數特定於 Java,即從 **.proto** 檔案自動生成的程式碼所在的包。
message Greet
將要建立/重新建立的物件的基類的名稱。
string greeting = 1; string username = 2;
這些是 **Greet** 類的屬性,以及資料型別和模式中標籤的位置。如果要新增新的標籤,其位置應為“3”。請注意,此位置整數對於確保實際資料緊湊且存在模式演變的空間非常重要。
Protocol Buffer 程式碼生成
現在我們已經定義了,讓我們安裝我們將用於為上述 **Greet** 類自動生成程式碼的“proto”二進位制檔案。可以在 "https://github.com/protocolbuffers/protobuf/releases/" 找到這些二進位制檔案。
根據作業系統選擇正確的二進位制檔案。我們將在 Windows 上安裝 proto 二進位制檔案,但 Linux 的步驟差別不大。
我們下載了 https://github.com/protocolbuffers/protobuf/releases/download/v27.3/protoc-27.3-win64.zip
驗證 Proto 編譯器設定
安裝後,確保您可以透過命令列訪問它:
protoc --version libprotoc 27.3
這確認 Protobuf 已正確安裝。現在讓我們繼續為 Java 建立上面描述的問候應用程式。
專案結構
這是我們將擁有的整體專案結構:
Java 中的問候應用程式
現在我們已經安裝了 **protoc**,我們可以使用 **protoc** 從 proto 檔案自動生成程式碼。讓我們先建立一個 Java 專案。
以下是我們將用於 Java 專案的 Maven 配置。請注意,它還包含 **Protobuf-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.tutorials.point</groupId>
<artifactId>protobuf-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.protobuf/protobuf-java -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>4.27.3</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 類
protoc --java_out=. greeting.proto
命令執行後,您會在當前目錄內的 **com > tutorialspoint > greeting** 資料夾下看到一個自動生成的類。
Greeting.java
此檔案包含一個類 **Greeting** 和一個介面 **GreetOrBuilder**,它將幫助我們對 **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, 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 com.google.flatbuffers.FlatBufferBuilder;
public class GreetReader {
public static void main(String[] args) throws FileNotFoundException, IOException {
// create a flat buffer builder
// it will be used to read Greet FlatBuffer
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
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();
java.nio.ByteBuffer buf = java.nio.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\protobuf-tutorial-1.0.jar com.tutorialspoint.greeting.GreetWriter Hello John Saving greeting to file: greeting_protobuf_output Saved greeting with following data to disk: greeting: Hello username: John
反序列化序列化的物件
然後,讓我們執行讀取器以從檔案系統反序列化物件。
java -cp .\target\protobuf-tutorial-1.0.jar com.tutorialspoint.greeting.GreetReader Reading from file greeting_protobuf_output Greeting: Hello Username: John
因此,正如我們所看到的,寫入器序列化並儲存到檔案中的資料,被讀取器正確地反序列化並相應地打印出來。
Python 中的問候應用程式
現在讓我們將同一個示例編寫為 Python 專案:
安裝 Protocol Buffers 庫
在我們繼續之前,我們需要安裝 **protobuf pip 包**。
pip install protobuf
我們所有的程式碼都將位於 **python** 目錄下。
從 proto 檔案生成 Python 類
在專案結構完成後,讓我們生成 Greet 類的程式碼:
protoc --python_out=. greeting.proto
執行此命令後,您會在當前目錄中看到一個自動生成的類 **greeting_pb2.py**。此類將幫助我們對 **Greet** 物件進行序列化和反序列化。
使用生成的 Python 類
現在,讓我們 **編寫** 資料的寫入器,它將接收 **使用者名稱** 和 **問候語** 作為輸入:
greetWriter.py
import greeting_pb2
import sys
greet = greeting_pb2.Greet()
greet.username = sys.argv[1]
greet.greeting = sys.argv[2]
filename = "greeting_protobuf_output";
print("Saving to file: " + filename)
f = open(filename, "wb")
f.write(greet.SerializeToString())
f.close()
print("Saved following greeting to disk: \n" + str(greet))
寫入器只需獲取 CLI 引數,建立 **Greet** 物件,將其序列化,然後將其轉儲到檔案中。
現在讓我們建立一個將讀取檔案的 **讀取器**:
greetReader.py
import greeting_pb2
greet = greeting_pb2.Greet()
filename = "greeting_protobuf_output";
print("Reading from file: " + filename)
f = open(filename, "rb")
greet.ParseFromString(f.read())
f.close()
print("Read greeting from disk: \n" + str(greet))
讀取器只需從同一檔案讀取,對其進行反序列化,然後列印有關問候語的資料。
序列化 Python 物件
現在,讓我們首先執行 **寫入器**。
py greetWriter.py Hola Jane Saving to file: greeting_protobuf_output Saved following greeting to disk: greeting: "Hola" username: "Jane"
反序列化 Python 物件
然後,讓我們執行 **讀取器**。
python greetReader.py Reading from file: greeting_protobuf_output Read greeting from disk: greeting: "Hola" username: "Jane"
因此,正如我們所看到的,寫入器序列化並儲存到檔案中的資料,同樣,這些資料被讀取器正確地反序列化並相應地打印出來。