Thank you very much, Florin. It works great! On Jan 16, 1:59 am, lucas_ro <florin...@gmail.com> wrote: > Yes, it is possible to serialize multiple protocol buffer messages > into a binary file and then load them from one by one. > > Please see below my sample: > > 1. The file that describe the message I want to serialize: > > message Person { > required int32 id = 1; > required string name = 2; > optional string email = 3; > required GendreType gendre = 4; > > enum GendreType { > M = 1; > F = 2; > } > > } > > message Catalog { > repeated Person persons = 1; > > } > > 2. The code that load the messages one by one (please see the > functions saveMultipleMessages and loadMultipleMessages) or at once: > > #include <cassert> > #include <iostream> > #include <fstream> > #include <google/protobuf/stubs/common.h> > #include <google/protobuf/io/zero_copy_stream.h> > #include <google/protobuf/io/zero_copy_stream_impl.h> > #include <google/protobuf/io/coded_stream.h> > #include "person.pb.h" > > using namespace std; > > static const char *gendres[] = {"M", "F"}; > > // > bool saveMultipleMessages(const char *fileName); > bool loadMultipleMessages(const char *fileName); > // > > int main() > { > GOOGLE_PROTOBUF_VERIFY_VERSION; > > fstream out("person.pb", ios::out | ios::binary | ios::trunc); > > // the container of person objects > Catalog catalog; > > // add person #1 > Person *p = catalog.add_persons(); > > p->set_id(23); > p->set_name("Bob"); > p->set_email("b...@mail.com"); > p->set_gendre(Person::M); > > // add person #2 > p = catalog.add_persons(); > > p->set_id(24); > p->set_name("Foo"); > p->set_gendre(Person::F); > > // serialize the container of the person objects > catalog.SerializeToOstream(&out); > out.close(); > > // deserialize the container of person objects > Catalog cat1; > > fstream in("person.pb", ios::in | ios::binary); > if (!cat1.ParseFromIstream(&in)) > { > cerr << "Failed to parse person.pb" << endl; > exit(1); > } > > for (int i = 0; i < cat1.persons_size(); ++i) > { > Person p = cat1.persons(i); > > cout << "ID: " << p.id() << endl; > cout << "name: " << p.name() << endl; > cout << "gendre: " << gendres[p.gendre()-1] << endl; > if (p.has_email()) > { > cout << "e-mail: " << p.email() << endl; > } > > cout << endl; > } > in.close(); > > // > if (saveMultipleMessages("person1.pb")) > { > loadMultipleMessages("person1.pb"); > } > > google::protobuf::ShutdownProtobufLibrary(); > > return 0; > > } > > // > bool saveMultipleMessages(const char *fileName) > { > fstream out(fileName, ios::out | ios::trunc | ios::binary); > if (!out) > { > cerr << "failed to open " << fileName << endl; > return false; > } > > ::google::protobuf::io::ZeroCopyOutputStream *raw_out = > new ::google::protobuf::io::OstreamOutputStream(&out); > ::google::protobuf::io::CodedOutputStream *coded_out = > new ::google::protobuf::io::CodedOutputStream(raw_out); > > // save the number of the messages to be serialized into the > output file > coded_out->WriteVarint32(2); > > std::string s; > > // message #1 > Person p; > p.set_id(1); > p.set_name("Bob"); > p.set_gendre(Person::M); > > p.SerializeToString(&s); > > coded_out->WriteVarint32(s.size()); > coded_out->WriteRaw(s.data(), s.size()); // ->WriteString(s) > // > > // message #2 > p.set_id(2); > p.set_name("Jane"); > p.set_email("j...@kinky.com"); > p.set_gendre(Person::F); > > p.SerializeToString(&s); > > coded_out->WriteVarint32(s.size()); > coded_out->WriteString(s); > // > > delete coded_out; > delete raw_out; > out.close(); > > return true; > > } > > // > bool loadMultipleMessages(const char *fileName) > { > fstream in(fileName, ios::in | ios::binary); > if (!in) > { > cerr << "failed to open " << fileName << endl; > return false; > } > > ::google::protobuf::io::ZeroCopyInputStream *raw_in = > new ::google::protobuf::io::IstreamInputStream(&in); > ::google::protobuf::io::CodedInputStream *coded_in = > new ::google::protobuf::io::CodedInputStream(raw_in); > > uint32_t n; > coded_in->ReadVarint32(&n); > cout << "#" << n << endl; > > // > std::string s; > > for (uint32_t i = 0; i < n; ++i) > { > uint32_t msgSize; > coded_in->ReadVarint32(&msgSize); > > if ((msgSize > 0) && > (coded_in->ReadString(&s, msgSize))) > { > // > Person p; > p.ParseFromString(s); > // > > cout << "ID: " << p.id() << endl; > cout << "name: " << p.name() << endl; > cout << "gendre: " << gendres[p.gendre()-1] << endl; > if (p.has_email()) > { > cout << "e-mail: " << p.email() << endl; > } > > cout << endl; > } > } > > delete coded_in; > delete raw_in; > in.close(); > > return true; > > } > > 3. I hope this is the aspect you asked for. > > Florin > > On Jan 15, 6:05 am, samarules <akm...@gmail.com> wrote: > > > > > Hi All, > > > I have what I believe is a simple task: write multiple protocol buffer > > messages into a single binary file and then read them back > > sequentially. When reading, I should not have to load the entire file > > in memory but read each protobuf object one at a time (with some > > buffering). An example application would to be store a large number of > > documents in a file, where each document is a single protobuf message. > > > Is this functionality available in C++? > > > Zia
-- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To post to this group, send email to proto...@googlegroups.com. To unsubscribe from this group, send email to protobuf+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.