株式市場データ(タイムスタンプ、入札、質問フィールドなど)をシリアル化するために、Googleプロトコルバッファーを使用しています。 1つのメッセージをファイルに保存し、問題なくデシリアライズできます。
複数のメッセージを単一のファイルに保存するにはどうすればよいですか?メッセージをどのように分離できるかわかりません。その場でファイルに新しいメッセージを追加できる必要があります。
Message
オブジェクトでwriteDelimitedTo(OutputStream)
およびparseDelimitedFrom(InputStream)
メソッドを使用することをお勧めします。 writeDelimitedTo
は、メッセージ自体の前にメッセージの長さを書き込みます。 parseDelimitedFrom
は、その長さを使用して1つのメッセージのみを読み取り、それ以上は読み取りません。これにより、複数のメッセージを単一のOutputStream
に書き込み、個別に解析できます。詳細については、 https://developers.google.com/protocol-buffers/docs/reference/Java/com/google/protobuf/MessageLite#writeDelimitedTo(Java.io.OutputStream) を参照してください。
ドキュメントから:
http://code.google.com/apis/protocolbuffers/docs/techniques.html#streaming
複数のメッセージのストリーミング
単一のファイルまたはストリームに複数のメッセージを書き込む場合、1つのメッセージが終了して次のメッセージが開始する場所を追跡するのはユーザー次第です。プロトコルバッファワイヤ形式は自己区切りではないため、プロトコルバッファパーサーはメッセージがどこで終了するかを判断できません。この問題を解決する最も簡単な方法は、メッセージ自体を書き込む前に各メッセージのサイズを書き込むことです。メッセージを読み戻すときは、サイズを読み取り、バイトを別のバッファーに読み取り、そのバッファーから解析します。 (バイトを別のバッファーにコピーしないようにするには、読み取りを特定のバイト数に制限するように指示できるCodedInputStreamクラス(C++とJavaの両方)をチェックしてください。)
Protobufには、最も外側のレコードごとにターミネーターが含まれていないため、それを自分で行う必要があります。最も簡単なアプローチは、データの前にレコードの長さを付けることです。個人的には、文字列ヘッダー(任意のフィールド番号)を記述し、次に「varint」として長さを書くというアプローチを使用する傾向があります。ただし、「繰り返し」要素を使用すると、固定長(通常は32ビットのリトルエンディアン)マーカーでも同様に機能します。このようなストレージでは、必要に応じて追加できます。
C++ソリューションを探している場合は、Kenton Varda 2015年8月頃にprotobufにパッチを提出 protoメッセージのシーケンスをシリアライズ/デシリアライズするwriteDelimitedTo()およびreadDelimitedFrom()呼び出しのサポートを追加します/ Javaこれらの呼び出しのバージョンと互換性のある方法でファイルから。残念ながら、このパッチはまだ承認されていないため、機能を自分でマージする必要がある場合。
もう1つのオプションは、Googleが他のプロジェクトを通じてコードを読み書きするオープンソースのprotobufファイルを持っていることです。たとえば、 または-tools ライブラリには、クラスへの RecordReader および RecordWriter が含まれています。これらは、ファイルへのプロトストリームをシリアル化/非シリアル化します。
外部依存関係がほとんどないこれらのクラスのスタンドアロンバージョンが必要な場合は、これらのクラスのみを含むor-toolsのフォークがあります。参照: https://github.com/moof2k/recordio
これらのクラスでの読み取りと書き込みは簡単です。
File* file = File::Open("proto.log", "w");
RecordWriter writer(file);
writer.WriteProtocolMessage(msg1);
writer.WriteProtocolMessage(msg2);
...
writer.Close();