protobuf数据的存储格式是什么?

时间:2013-06-25 01:34:05

标签: serialization protocol-buffers

.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文件中输入的可读字符串而不是“数字格式”,为什么会这样?

1 个答案:

答案 0 :(得分:1)

The encoding is described here

如果没有另一端的例子,那就很难准确回答,但对你所看到的内容有两种可能的解释:

  1. 您已在代码中明确切换为TextFormat;这是不太可能的 - 事实上,TextFormat的主要用途是调试等
  2. 更有可能的是,您只是在二进制文件中看到来自消息的文本数据; text被编码为UTF-8,因此如果你在文本编辑器中打开一个protobuf文件,它的各个部分将显示可读以显示文件中的内容
  3. 真正的问题是:输出文件中的实际字节是什么?如果是这样的话:

      

    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

    然后二进制格式;但请注意,其中大多数只是字符串"helloworld,this is a protobuf writer"的UTF-8 - 它通过大小来支配消息:

      

    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:header:field 1,varint
    • 88-95-06:值(十进制)101000作为varint
    • 12:header:field 2,length-prefixed
    • 24:值(十进制)36作为varint(字符串的长度,以字节为单位)

    需要注意的要点:

    • 如果你的信息被文字支配,那么它的大部分内容即使是二进制形式也会看起来是人类可读的
    • 看看管理费用;它对6个字节进行编码整个剩余的消息,其中3个字节是数据(101000) - 所以实际上只有3个字节作为开销丢失了;现在比较和对比xml,json等,以了解protobuf正在做些什么来帮助你