どのように私はPythonのいるProtobufを使用して、バイナリC ++いるProtobufデータを読みますか。
-
13-09-2019 - |
質問
の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関数を使用してから来ています。これを解消するために、私はこのtemproaryコードを使用しています:
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でファイルを開いていたときに読むことをどのくらい知っているように、それはバイナリサイズだと、私は、各メッセージの前に付けます。
解決
私は、Pythonでの専門家ではないんだけど、あなたは新しい文字列型か何かを構築することなく、file.read()
にmessage.ParseFromString(...)
操作の結果を渡すことができます。
他のヒント
Pythonの文字列は任意の文字を含めることができ、すなわち、それらは、直接「バイナリ」のデータを保持することが可能です。 「バイナリ」の文字列から変換する必要があってはなりません。