3

.proto 文件:

package lm;
message helloworld
{
     required int32 id = 1;
     required string str = 2;
     optional int32 opt = 3;
}

writer.cc 文件:

#include <iostream>
#include <string>
#include "lm.helloworld.pb.h"
#include <fstream>
using namespace std;

int main()
{
    lm::helloworld msg1;
    msg1.set_id(101000);
    msg1.set_str("helloworld,this is a protobuf writer");
    fstream output("log", ios::out | ios::trunc | ios::binary);
    string _data;
    msg1.SerializeToString(&_data);
    cout << _data << endl;
    if(!msg1.SerializeToOstream(&output))
    {
        cerr << "Failed to write msg" << endl;
        return -1;
    }
    return 0;
}

reader.cc 文件:

#include <iostream>
#include <fstream>
#include <string>
#include "lm.helloworld.pb.h"
using namespace std;

void ListMsg(const lm::helloworld & msg)
{
    cout << msg.id() << endl;
    cout << msg.str() << endl;
}

int main(int argc, char* argv[])
{
    lm::helloworld msg1;
    {
        fstream input("log", ios::in | ios::binary);
        if (!msg1.ParseFromIstream(&input))
        {
            cerr << "Failed to parse address book." << endl;
            return -1;
        }
    }

    ListMsg(msg1);
    return 0;
}

这是一个使用 protobuf 的简单读写器模型。但是日志中的内容是在 write.cc 文件中键入的可读字符串,而不是“数字格式”,这是为什么呢?

4

1 回答 1

2

这里描述了编码

如果没有另一端出现的示例,这有点难以准确回答,但是对于您所看到的内容有两种可能的解释:

  1. 您已在代码中明确切换到TextFormat;这不太可能 - 事实上,主要用途TextFormat是调试等
  2. 更有可能的是,您只是在二进制文件中看到消息中的文本数据;文本被编码为 UTF-8,因此如果您在文本编辑器中打开一个 protobuf 文件,它的部分内容将看起来足够可读以显示文件中的某些内容

真正的问题是:输出文件中的实际字节数是多少?如果是这样的:

08-88-95-06-12-24-68-65-6C-6C-6F-77-6F-72-6C-64-2C-74-68-69-73-20-69-73-20- 61-20-70-72-6F-74-6F-62-75-66-20-77-72-69-74-65-72

就是二进制格式;但请注意,其中大部分只是字符串的 UTF-8 "helloworld,this is a protobuf writer"- 它以绝对大小支配消息:

68-65-6C-6C-6F-77-6F-72-6C-64-2C-74-68-69-73-20-69-73-20-61-20-70-72-6F-74- 6F-62-75-66-20-77-72-69-74-65-72

因此,如果您查看任何文本编辑器,它会在开头显示为一些乱码,然后是清晰易读的helloworld,this is a protobuf writer.

这里的“二进制”是开头的位:

08-88-95-06-12-24

这是:

  • 08:标题:字段 1,varint
  • 88-95-06:值(十进制)101000 作为 varint
  • 12:标题:字段 2,以长度为前缀
  • 24:值(十进制) 36 作为 varint(字符串的长度,以字节为单位)

需要注意的关键点:

  • 如果您的消息以文本为主,是的,即使是二进制形式,它的大部分也会看起来是人类可读的
  • 看看开销;它为 6 个字节来编码整个消息的其余部分,其中3 个字节是数据(101000) - 所以实际上只有 3 个字节作为开销丢失;现在与 xml、json 等进行比较和对比,以了解 protobuf 正在做什么来帮助您
于 2013-06-25T07:18:41.517 回答