Protocol buffers 序列化消息中的新行字符

Protocol buffers 序列化消息中的新行字符,protocol-buffers,Protocol Buffers,某些protobuf消息序列化为字符串时,其内部有新行字符\n。通常,当消息的第一个字段是字符串时,新行字符在消息之前加上前缀。但是WA也发现了中间有新行字符的消息。 换行符的问题是,您希望将消息逐行保存到一个文件中。新行字符打断了行并使消息无效 示例.proto syntax = "proto3"; package data_sources; message StringFirst { string key = 1; bool valid = 2; } message Strin

某些protobuf消息序列化为字符串时,其内部有新行字符
\n
。通常,当消息的第一个字段是字符串时,新行字符在消息之前加上前缀。但是WA也发现了中间有新行字符的消息。

换行符的问题是,您希望将消息逐行保存到一个文件中。新行字符打断了行并使消息无效

示例.proto

syntax = "proto3";

package data_sources;

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

message StringSecond {
  bool valid = 1;
  string key = 2;
}
示例.py

from protocol_buffers.data_sources.example_pb2 import StringFirst, StringSecond

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

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

这是预期/期望的行为吗?如何防止新行字符?

protobuf是一个二进制协议(除非您讨论的是可选的json)。因此:无论何时,只要您以任何方式将其视为文本,您都是在错误地使用它,行为将是未定义的。这包括担心是否存在CR/LF字符,但也包括nul字符(0x00),在许多框架(特别是C字符串)中,在基于文本的API中,nul字符通常被解释为字符串结尾

具体而言:

  • LF(0x0A)与“字段1,长度前缀”的字段标题相同
  • CR(0x0D)与“字段1,固定32位”的字段标题相同
  • 0x00、0x0A或0x0D中的任何一个都可以作为长度前缀出现(表示长度为0、10或13)
  • 0x00、0x0A或0x0D中的任何一个都可以在二进制数据中自然出现(
    字节
  • 0x00、0x0A或0x0D中的任何一个都可以在任何数字类型中自然出现
  • 0x0A或0x0D可以在文本数据中自然出现(如果您的原始框架允许字符串中任意使用nul字符,那么0x00也可以出现,所以…不是C字符串)
  • 可能还有一系列其他的事情
因此:再次-如果包含“特殊”文本字符是有问题的:你用错了


将二进制数据作为文本处理的最常见方法是使用base-N编码;base-16(十六进制)便于显示和读取,但base-64在传输相同字节数所需的字符数方面更为有效。因此,如果可能的话:根据需要转换为base-64或从base-64转换为base-64。Base-64从不包含任何不可打印的字符,因此您将永远不会遇到CR/LF/nul。

谢谢。为了回答的完整性,以下是如何将其转换为base-16和base-16:
text=bytes.hex(message.SerializeToString())
message.ParseFromString(bytes.fromhex(text))