Google protobuf の Python バージョンでは、次の情報しか得られません。
SerializeAsString()
C++ バージョンでは次の両方が得られます。
SerializeToArray(...)
SerializeAsString()
C++ ファイルにバイナリ形式で書き込んでいますが、この方法を維持したいと考えています。そうは言っても、バイナリ データを Python に読み込み、それを文字列であるかのように解析する方法はありますか?
これは正しい方法ですか?
binary = get_binary_data()
binary_size = get_binary_size()
string = None
for i in range(len(binary_size)):
string += i
message = new MyMessage()
message.ParseFromString(string)
アップデート:
ここに新しい例と問題があります:
message_length = 512
file = open('foobars.bin', 'rb')
eof = False
while not eof:
data = file.read(message_length)
eof = not data
if not eof:
foo_bar = FooBar()
foo_bar.ParseFromString(data)
行に到達すると、次のfoo_bar.ParseFromString(data)
エラーが発生します。
Exception Type: DecodeError
Exception Value: Too many bytes when decoding varint.
更新 2:
バイナリ データのパディングが protobuf をスローしていたことが判明しました。メッセージが示すように、送信されるバイト数が多すぎます (この場合は、パディングを参照していました)。
SerializeToArray
このパディングは、固定長バッファーでC++ の protobuf 関数を使用することで発生します。これを解消するために、次の一時的なコードを使用しました。
message_length = 512
file = open('foobars.bin', 'rb')
eof = False
while not eof:
data = file.read(message_length)
eof = not data
string = ''
for i in range(0, len(data)):
byte = data[i]
if byte != '\xcc': # yuck!
string += data[i]
if not eof:
foo_bar = FooBar()
foo_bar.ParseFromString(string)
ここに設計上の欠陥があると思います。可変長配列をバイナリ ファイルに書き込むように、C++ コードを再実装します。protobuf のドキュメントでアドバイスされているように、各メッセージにバイナリ サイズのプレフィックスを付けて、Python でファイルを開くときにどれだけ読むべきかを把握できるようにします。