我是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_);
使用此代码后,文件显示为空白。我哪里错了?
答案 0 :(得分:4)
我试过根据我收到的消息使用CodedOutputStream但是它 似乎没有在文件中写任何东西。
我怀疑您的问题是您没有删除CodedOutputStream
或FileOutputStream
。这些对象缓冲输出并在其析构函数中刷新缓冲区,因此如果您永远不会销毁它们,它们将不会写入最后一个缓冲区,在这种情况下它是唯一的缓冲区。
我建议在堆栈上分配这些对象(作为局部变量)。然后你不可能忘记摧毁它们。
有了这个,这里的代码使用CodedInputStream
和CodedOutputStream
来读/写分隔的消息。每条消息的前缀都是一个指示大小的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;
}