繁体   English   中英

协议缓冲区:如何将多个消息序列化和反序列化为文件(c ++)?

[英]protocol buffers: how to serialize and deserialize multiple messages into a file (c++)?

我是Protocol Buffers和c ++的新手,但我的任务要求我使用这两个。 我想多次将数据结构(消息)写入单个文件,并能够读取数据。 我可以读取和写入一条消息,但多条消息证明更难。 我已经找了几个小时的答案,但我似乎无法将数据作为结构读取。 任何示例代码或指针都非常有用。

这是我的结构格式:

    typedef struct Entry
       {
          char  name[ NAME_MAX];
          int   id;
          int   age;
          char  DoB[32]; 
       } entry;

这就是我用来写入文件的内容:

    Person_File file;
    fstream output("file", ios::out | ios::trunc | ios::binary);
    file.SerializeToOstream(&output);

我试图更改文件编辑选项以追加而不是截断,但这不允许我以我想要的格式读取数据。

这是我用来阅读的内容:

    fstream input("file", ios::in | ios::binary);
    file.ParseFromIstream(&input);

这些是我的.proto文件的内容:

    message Person {


message File {
    required string pname =1;
    required int32 id =2;
    required int32 age =3;
    required string DoB =4;
}

repeated File file =1;

}

从我所做的所有搜索看来,CodedInputStream / CodedOutputStream似乎是我最好的选择,但我找不到任何详细的例子或解释来帮助我理解。 我知道协议缓冲区不是自我划分的,这可能是我无法以原始格式读回我的消息的原因。 任何帮助,将不胜感激。 谢谢

编辑:我已经尝试使用CodedOutputStream基于我收到的消息但它似乎没有写入任何文件。

    int fd = open("file.txt",O_WRONLY | O_APPEND | O_CREAT);

    FileOutputStream* file_ostream_ = new FileOutputStream(fd);
    CodedOutputStream* ostream_ = new CodedOutputStream(file_ostream_);


ostream_->WriteLittleEndian32(file.ByteSize());
    file.SerializeToCodedStream(ostream_);

使用此代码后,该文件显示为空白。 我哪里错了?

我已经尝试使用基于我收到的消息的CodedOutputStream但它似乎没有在文件中写入任何内容。

我怀疑你的问题是你没有删除CodedOutputStreamFileOutputStream 这些对象缓冲输出并在其析构函数中刷新缓冲区,因此如果您永远不会销毁它们,它们将不会写入最后一个缓冲区,在这种情况下它是唯一的缓冲区。

我建议在堆栈上分配这些对象(作为局部变量)。 然后你不可能忘记摧毁它们。

有了这个,这里的代码使用CodedInputStreamCodedOutputStream来读/写分隔的消息。 每条消息的前缀都是一个指示大小的varint,其格式与Java Protobuf库的writeDelimitedTo() / parseDelimitedFrom() (一种从未进入C ++库的特性)相同。

bool writeDelimitedTo(
    const google::protobuf::MessageLite& message,
    google::protobuf::io::ZeroCopyOutputStream* rawOutput) {
  google::protobuf::io::CodedOutputStream output(rawOutput);

  // Write the size.
  const int size = message.ByteSize();
  output.WriteVarint32(size);

  uint8_t* buffer = output.GetDirectBufferForNBytesAndAdvance(size);
  if (buffer != NULL) {
    // Optimization:  The message fits in one buffer, so use the faster
    // direct-to-array serialization path.
    message.SerializeWithCachedSizesToArray(buffer);
  } else {
    // Slightly-slower path when the message is multiple buffers.
    message.SerializeWithCachedSizes(&output);
    if (output.HadError()) return false;
  }

  return true;
}

bool readDelimitedFrom(
    google::protobuf::io::ZeroCopyInputStream* rawInput,
    google::protobuf::MessageLite* message) {
  google::protobuf::io::CodedInputStream input(rawInput);

  // Read the size.
  uint32_t size;
  if (!input.ReadVarint32(&size)) return false;

  // Tell the stream not to read beyond that size.
  auto limit = input.PushLimit(size);

  // Parse the message.
  if (!message->MergePartialFromCodedStream(&input)) return false;
  if (!input.ConsumedEntireMessage()) return false;

  // Release the limit.
  input.PopLimit(limit);

  return true;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM