将 protobuf 字节类型存储在二进制文件中

Posted

技术标签:

【中文标题】将 protobuf 字节类型存储在二进制文件中【英文标题】:Store protobuf byte type inside a binary file 【发布时间】:2019-05-17 22:35:40 【问题描述】:

我正在尝试拆分和合并二进制文件,原因与此问题无关,我使用 protobuf 将文件 char* 存储在 protobuf 字节类型中

序列化 char* 的代码如下所示:

char* buffer = new char[buffer_size];
ifstream fileStream;

fileStream.open(fileName,ios::in | ios::binary);

//stuff here

Data *data = new Data(); // Protobuf Constructor

fileStream.read(buffer, buffer_size);
data->set_payload(buffer);
data->set_piece_no(piece_no);

.proto 文件:

 syntax = "proto3";
 message Data 
 int32 piece_no = 1;
 bytes payload = 2;
 

然后我尝试像这样组合所有部分:

ofstream fileOutput;
fileOutput.open("out.bin", ios::out | ios::binary);
fileOutput << data->payload();

但遗憾的是这不起作用,生成的二进制文件比原始文件小得多。

然后我怀疑字节可能包含空字符 \0,因此字节实际上已被截断。

为了验证我的假设,我执行以下操作:

Data *data = new Header();
data->set_payload("hel\0lo");
data->set_piece_no(piece_no);

ofstream fileOutput;
fileOutput.open("out.bin",ios::out | ios::binary);
fileOutput << data->payload();

在文本编辑器(vscode)中打开二进制文件显示如下:

hel

但是下面的代码:

string data("hel\0lo",6);
ofstream fileOutput;
fileOutput.open("out.bin", ios::out | ios::binary);
fileOutput << data;

显示以下内容:

hel?lo

我怎样才能准确地输出我输入到 protobuf 中的内容,而不会因为任意空字节而被截断?

【问题讨论】:

如果您改用std::ostream.write(...) 会怎样?我假设你知道长度。如果没有,您需要将其保存在某处,因为 strlen 无法处理嵌入 0 字节的数据。 【参考方案1】:

如果你传递一个字符串文字,那么它会这样对待它并且只读取到第一个空终止符。

相反,您可以像上一个示例一样直接传递std::string

请参阅https://developers.google.com/protocol-buffers/docs/reference/cpp-generated#oneof 中的“单数字符串字段 (proto3)”下的内容

【讨论】:

以上是关于将 protobuf 字节类型存储在二进制文件中的主要内容,如果未能解决你的问题,请参考以下文章

Protobuf底层存储原理

Protobuf编码

通过 Google Protobuf 发送二进制文件数据

protobuf3基础语法

Protobuf 数据格式

c++怎样申请一个已知字节的空间,然后按位操作把字节的每位都存储满,然后再存入一个二进制文件中