Python protobuf를 사용하여 Binain C ++ Protobuf 데이터를 어떻게 읽습니까?
-
13-09-2019 - |
문제
Google Protobuf의 Python 버전은 다음에만 제공합니다.
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.
Update 2:
이진 데이터의 패딩이 프로토 부프를 버리고있는 것으로 나타났습니다. 메시지에서 알 수 있듯이 너무 많은 바이트가 전송되었습니다 (이 경우 패딩을 참조했습니다).
이 패딩은 C ++ protobuf 함수를 사용하는 것입니다. SerializeToArray
고정 길이 버퍼에. 이를 제거하기 위해이 온도 코드를 사용했습니다.
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(...)
새 문자열 유형을 만들 필요없이.
다른 팁
파이썬 문자열에는 모든 문자가 포함될 수 있습니다. 즉, "바이너리"데이터를 직접 보유 할 수 있습니다. 문자열에서 "바이너리"로 변환 할 필요가 없어야합니다.