Google Protocol Bufferの概要
1. 概要
この記事では、言語に依存しない有名なバイナリデータ形式であるGoogle Protocol Buffer(protobuf)について説明します。 プロトコルでファイルを定義し、次にそのプロトコルを使用して、Java、C ++、C#、Go、Pythonなどの言語でコードを生成できます。
これは、フォーマット自体の紹介記事です。 Spring Webアプリケーションでこの形式を使用する方法を知りたい場合は、this articleを参照してください。
2. Mavenの依存関係の定義
Javaのプロトコルバッファを使用するには、Maven依存関係をprotobuf-javaに追加する必要があります。
com.google.protobuf
protobuf-java
${protobuf.version}
3.2.0
3. プロトコルの定義
例から始めましょう。 protobuf形式で非常に単純なプロトコルを定義できます。
message Person {
required string name = 1;
}
これは、必須フィールドが1つしかないPersonタイプの単純なメッセージのプロトコルです。stringタイプの名前です。
プロトコルを定義するより複雑な例を見てみましょう。 個人の詳細をprotobuf形式で保存する必要があるとしましょう。
パッケージprotobuf;
package protobuf;
option java_package = "com.example.protobuf";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
repeated string numbers = 4;
}
message AddressBook {
repeated Person people = 1;
}
私たちのプロトコルは、PersonとAddressBook.の2種類のデータで構成されています。コードを生成すると(これについては後のセクションで詳しく説明します)、これらのクラスはAddressBookProtos内の内部クラスになります。クラス。
必須のフィールドを定義する場合、つまり、そのようなフィールドなしでオブジェクトを作成するとExceptionが発生する場合は、requiredキーワードを使用する必要があります。
optionalキーワードを使用してフィールドを作成すると、このフィールドを設定する必要がなくなります。 repeatedキーワードは、可変サイズの配列型です。
すべてのフィールドにはインデックスが付けられます。番号1で示されるフィールドは、バイナリファイルの最初のフィールドとして保存されます。 2でマークされたフィールドが次に保存されます。 これにより、メモリ内でのフィールドの配置をより適切に制御できます。
4. ProtobufファイルからのJavaコードの生成
ファイルを定義したら、そこからコードを生成できます。
まず、マシン上でinstall protobufを実行する必要があります。 これを実行すると、protocコマンドを実行してコードを生成できます。
protoc -I=. --java_out=. addressbook.proto
protocコマンドは、addressbook.protoファイル.からJava出力ファイルを生成します。-Iオプションは、protoファイルが存在するディレクトリを指定します。 java-outは、生成されたクラスが作成されるディレクトリを指定します。 __
生成されたクラスには、定義されたメッセージのセッター、ゲッター、コンストラクター、ビルダーがあります。 また、protobufファイルを保存し、バイナリ形式からJavaクラスにデシリアライズするためのいくつかのutilメソッドもあります。
5. Protobuf定義メッセージのインスタンスの作成
生成されたコードを使用して、PersonクラスのJavaインスタンスを簡単に作成できます。
String email = "[email protected]";
int id = new Random().nextInt();
String name = "Michael Program";
String number = "01234567890";
AddressBookProtos.Person person =
AddressBookProtos.Person.newBuilder()
.setId(id)
.setName(name)
.setEmail(email)
.addNumbers(number)
.build();
assertEquals(person.getEmail(), email);
assertEquals(person.getId(), id);
assertEquals(person.getName(), name);
assertEquals(person.getNumbers(0), number);
目的のメッセージタイプでnewBuilder()メソッドを使用することにより、流暢なビルダーを作成できます。 すべての必須フィールドを設定した後、build()メソッドを呼び出して、Personクラスのインスタンスを作成できます。
6. Protobufのシリアル化と逆シリアル化
Personクラスのインスタンスを作成したら、作成したプロトコルと互換性のあるバイナリ形式でディスクに保存します。 AddressBookクラスのインスタンスを作成し、そのオブジェクトに1人の人物を追加するとします。
次に、そのファイルをディスクに保存します。自動生成されたコードには、使用できるwriteTo()utilメソッドがあります。
AddressBookProtos.AddressBook addressBook
= AddressBookProtos.AddressBook.newBuilder().addPeople(person).build();
FileOutputStream fos = new FileOutputStream(filePath);
addressBook.writeTo(fos);
そのメソッドを実行すると、オブジェクトはバイナリ形式にシリアル化され、ディスクに保存されます。 そのデータをディスクからロードし、それをAddressBookオブジェクトに逆シリアル化するには、mergeFrom()メソッドを使用できます。
AddressBookProtos.AddressBook deserialized
= AddressBookProtos.AddressBook.newBuilder()
.mergeFrom(new FileInputStream(filePath)).build();
assertEquals(deserialized.getPeople(0).getEmail(), email);
assertEquals(deserialized.getPeople(0).getId(), id);
assertEquals(deserialized.getPeople(0).getName(), name);
assertEquals(deserialized.getPeople(0).getNumbers(0), number);
7. 結論
この簡単な記事では、データをバイナリ形式で記述および保存するための標準、Google Protocol Bufferを紹介しました。
単純なプロトコルを作成し、定義されたプロトコルに準拠するJavaインスタンスを作成しました。 次に、protobufを使用してオブジェクトをシリアライズおよびデシリアライズする方法を見ました。
これらすべての例とコードスニペットの実装は、GitHub projectにあります。これはMavenプロジェクトであるため、そのままインポートして実行するのは簡単です。