将多个消息存储在一个协议缓冲区二进制文件中
Storing multiple messages in one protocol buffer binary file
我有重复的消息,我想存储在一个文件中。目前,我必须将这个重复的消息包装在另一个消息中。有办法解决这个问题吗?
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;
}
协议缓冲区文档中的"技术"部分对重复消息的描述如下:
如果你想写多条消息对于单个文件或流,它是up的给你留个踪迹在哪里消息结束,下一个开始。的协议缓冲区线格式不是自定界,所以协议缓冲区解析器无法确定消息自己结束。最简单的解决这个问题的方法是写你面前的每条信息的大小编写消息本身。当你把信息读回来,你读大小,然后将字节读入分离缓冲区,然后从中解析缓冲区。(如果你想避免复制字节到一个单独的缓冲区,签出CodedInputStream类(在两者中)c++和Java),它可以被告知将读取限制为一定数量的字节。)
在c++和Java中也有一种常规的实现方法。看看这个堆栈溢出线程的详细信息:在Java中是否有与协议缓冲区分隔的I/O函数等效的c++ ?
Protobuf不支持此功能。它可以用来序列化一条消息,但是这个序列化的消息不包含关于它的类型(Box或Boxes)和长度的信息。所以如果你想存储多条消息你还必须包括消息的类型和长度。编写算法(用伪语言)可以像这样:
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)
}
}
我正在研究这个问题,最后选择了Parquet。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();
它可能不适合您的用例,但我认为它值得在这里提及。
在java中可以使用分隔符消息。关于c++,请参阅在Java中是否有与协议缓冲区分隔的I/O函数等效的c++ ?
基本上在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你需要算出
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 如何制作一个简单的Winboard协议
- 是否有一个C++CalDav协议库可以连接到iCloud//Yahoo
- 用c++设计了一个文件传输协议
- 为分布式系统构建了一个自定义的C++通信协议
- 在c++中,如何声明一个接受任意对象的向量数组作为协议的函数
- 如何将两个不同的协议封装到一个api中
- 协议缓冲区问题,多个序列化成一个二进制文件
- 协议缓冲区:如何将多条消息序列化和反序列化为一个文件 (C++)
- 将多个消息存储在一个协议缓冲区二进制文件中