我有重复的消息,我想存储在一个文件中。目前,我必须在另一条消息中包装此重复消息。有办法解决这个问题吗?
package foo;
message Box {
required int32 tl_x = 1;
required int32 tl_y = 2;
required int32 w = 3;
required int32 h = 4;
}
message Boxes {
repeated Box boxes = 1;
}
答案 0 :(得分:12)
以下是Protocol Buffers文档中有关重复消息的"Techniques"部分的内容:
如果要编写多条消息 单个文件或流,它已启动 告诉你一个人在哪里 消息结束,下一个消息开始。该 协议缓冲区的有线格式不是 自定界,所以协议缓冲区 解析器无法确定何处 消息自行结束。最简单的 解决这个问题的方法是写 你之前每封邮件的大小 写消息本身。当你 阅读回来的消息,你读 大小,然后将字节读入a 单独的缓冲区,然后从中解析 缓冲。 (如果你想避免复制 字节到单独的缓冲区,检查 CodedInputStream类(两者都有) 可以告诉的C ++和Java) 限制读取到一定数量 字节)。
还有一种在C ++和Java中实现它的传统方法。有关详细信息,请查看此Stack Overflow线程:Are there C++ equivalents for the Protocol Buffers delimited I/O functions in Java?
答案 1 :(得分:6)
Protobuf不支持此功能。它可用于序列化一条消息,但此序列化消息不包含有关其类型(Box或Box)和长度的信息。因此,如果您想存储多条消息,您还必须包含消息的类型和长度。编写算法(伪语言)可能如下所示:
for every message {
write(type_of_message) // 1 byte long
write(length_of_serialized_message) // 4 bytes long
write(serialized_message)
}
加载算法:
while(end_of_file) {
type = read(1) // 1 byte
length = read(4) // 4 bytes
buffer = read(length)
switch (type) {
case 1:
deserialise_message_1(buffer)
case 2:
deserialise_message_2(buffer)
}
}
答案 2 :(得分:1)
在java中,您可以使用分隔的消息。对于C ++,请参阅Are there C++ equivalents for the Protocol Buffers delimited I/O functions in Java?
基本上在C ++中根据上述
const unsigned bufLength = 256;
unsigned char buffer[bufLength];
Message protoMessage;
google::protobuf::io::ArrayOutputStream arrayOutput(buffer, bufLength);
google::protobuf::io::CodedOutputStream codedOutput(&arrayOutput);
codedOutput.WriteLittleEndian32(protoMessage.ByteSize());
protoMessage.SerializeToCodedStream(&codedOutput);
和python你需要解决它
答案 3 :(得分:0)
我只是在解决这个问题,最后选择了。 Parquet非常适合在文件中存储一堆Protobuf消息,并使其在以后的工作中更加容易。
这段代码将创建Parquet文件:
Path path = new Path("/tmp/mydata.parq");
CompressionCodecName codecName = CompressionCodecName.SNAPPY;
int blockSize = 134217728;
int pageSize = 1048576;
boolean enableDictionary = true;
boolean validating = false;
ProtoParquetWriter<Message> writer
= new ProtoParquetWriter<>(
path,
Box.class,
codecName,
blockSize,
pageSize,
enableDictionary,
validating
);
for (Message message : messages) {
writer.write(message);
}
writer.close();
它可能不适合您的用例,但我认为在这里值得一提。