كيف يمكنني قراءة بيانات Protobuf الثنائية C ++ باستخدام Python Protobuf؟
-
13-09-2019 - |
سؤال
يعطينا نسخة Python من Google Protobuf فقط:
SerializeAsString()
حيث يعطينا نسخة C ++ كلاهما:
SerializeToArray(...)
SerializeAsString()
نكتب إلى ملف C ++ لدينا بتنسيق ثنائي، ونود أن نحتفظ به بهذه الطريقة. ومع ذلك، هل هناك طريقة لقراءة البيانات الثنائية في بيثون وتحليلها كما لو كانت سلسلة؟
هل هذه هي الطريقة الصحيحة للقيام بذلك؟
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 قبالة؛ تم إرسال الكثير من البايتات، حيث تشير الرسالة (في هذه الحالة كانت تشير إلى الحشو).
هذه الحشو تأتي من استخدام وظيفة C ++ Protobuf، SerializeToArray
على المخزن المؤقت بطول ثابت. للقضاء على هذا، استخدمت هذا الرمز 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.
المحلول
أنا لست خبيرا مع بيثون، لكن يمكنك تمرير نتيجة file.read()
عملية message.ParseFromString(...)
دون الحاجة إلى بناء نوع سلسلة جديدة أو أي شيء.
نصائح أخرى
يمكن أن تحتوي سلاسل بيثون على أي شخصية، أي أنها قادرة على عقد بيانات "ثنائية" مباشرة. يجب ألا تكون هناك حاجة للتحويل من سلسلة إلى "ثنائية".