Символ новой строки в сериализованных сообщениях - PullRequest
0 голосов
/ 28 января 2019

Некоторые сообщения protobuf при сериализации в строку имеют символ новой строки \n внутри.Обычно, когда первое поле сообщения является строкой, перед сообщением добавляется символ новой строки.Но вы также нашли сообщения с символом новой строки где-то посередине.

Проблема с символом новой строки заключается в том, что вы хотите сохранять сообщения в один файл построчно.Символ новой строки разрывает строку и делает сообщение недействительным.

example.proto

syntax = "proto3";

package data_sources;

message StringFirst {
  string key = 1;
  bool valid = 2;
}

message StringSecond {
  bool valid = 1;
  string key = 2;
}

example.py

from protocol_buffers.data_sources.example_pb2 import StringFirst, StringSecond

print(StringFirst(key='some key').SerializeToString())
print(StringSecond(key='some key').SerializeToString())

output

b'\n\x08some key'
b'\x12\x08some key'

Это ожидаемое / желаемое поведение?Как можно предотвратить символ новой строки?

1 Ответ

0 голосов
/ 28 января 2019

protobuf - это двоичный протокол (если вы не говорите о необязательном json).Итак, каждый раз, когда вы воспринимаете его как текстовый , любым способом , вы используете его неправильно и поведение будет неопределенным.Это включает беспокойство о том, существуют ли символы CR / LF, но также включает такие вещи, как нуль-символ (0x00), который часто интерпретируется как конец строки в текстовых API во многих средах (в частности, в C-строки).

В частности:

  • LF (0x0A) идентичен заголовку поля для «поля 1 с префиксом длины»
  • CR (0x0D):идентичен заголовку поля для «поля 1, фиксированный 32-разрядный»
  • любой из 0x00, 0x0A или 0x0D может встречаться в качестве префикса длины (для обозначения длины 0, 10 или 13)
  • любой из 0x00, 0x0A или 0x0D может встречаться естественным образом в двоичных данных (bytes)
  • любой из 0x00, 0x0A или 0x0D может встречаться естественным образом в любом числовом типе
  • 0x0A или 0x0Dможет происходить естественным образом в текстовых данных (как 0x00, если ваша исходная структура допускает nul-символов произвольно в строках, так что ... не в C-строках)
  • и, возможно, в ряде других вещей

Итак: еще раз - если включить «специальные»текстовые символы проблематичны: вы используете его неправильно .

Наиболее распространенный способ обработки двоичных данных в виде текста - это использование кодировки base-N;base-16 (hex) удобен для отображения и чтения, но base-64 более эффективен с точки зрения количества символов, необходимых для передачи одинакового количества байтов.Поэтому, если возможно: конвертируйте в / из base-64 по мере необходимости.Base-64 никогда не содержит никаких непечатных символов, поэтому вы никогда не встретите CR / LF / nul.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...