intmain() { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION;
将数据序列化为 XML。这种方法非常有吸引力,因为 XML(差不多)是人类可读的,并且有许多语言的绑定库。如果你想与其他应用程序/项目共享数据,这可能是一个不错的选择。然而,XML 是众所周知需要更多的空间,并且编码/解码 XML 会对应用程序造成巨大的性能损失。此外,导航 XML DOM 树比通常在类中导航简单字段要复杂得多。
addressbook.proto:6:12: Explicit 'optional' labels are disallowed in the Proto3 syntax. To define 'optional' fields in Proto3, simply remove the 'optional' label, as fields are 'optional' by default.
package 声明:这有助于防止不同项目之间的命名冲突。在 C++ 中,生成的类将放在与包名匹配的 namespace (命名空间)中。例如定一个类
#if GOOGLE_PROTOBUF_VERSION < 3005000 #error This file was generated by a newer version of protoc which is #error incompatible with your Protocol Buffer headers. Please update #error your headers. #endif #if 3005000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif
3.5 The Protocol Buffer API
让我们看看一些生成的代码,看看编译器为你创建了哪些类和函数。如果你查看 addressbook.pb.h,你会发现你在 addressbook.proto 中指定的每条 message 都有一个对应的类。仔细观察 Person 类,你可以看到编译器已为每个字段生成了访问器。例如,对于 name ,id,email 和 phone 字段,你可以使用以下方法(proto2生成的如下):
// Parsing --------------------------------------------------------- // Methods for parsing in protocol buffer format. Most of these are // just simple wrappers around MergeFromCodedStream(). Clear() will be // called before merging the input.
// Fill the message with a protocol buffer parsed from the given input // stream. Returns false on a read error or if the input is in the wrong // format. A successful return does not indicate the entire input is // consumed, ensure you call ConsumedEntireMessage() to check that if // applicable. boolParseFromCodedStream(io::CodedInputStream* input); // Like ParseFromCodedStream(), but accepts messages that are missing // required fields. boolParsePartialFromCodedStream(io::CodedInputStream* input); // Read a protocol buffer from the given zero-copy input stream. If // successful, the entire input will be consumed. boolParseFromZeroCopyStream(io::ZeroCopyInputStream* input); // Like ParseFromZeroCopyStream(), but accepts messages that are missing // required fields. boolParsePartialFromZeroCopyStream(io::ZeroCopyInputStream* input); // Read a protocol buffer from the given zero-copy input stream, expecting // the message to be exactly "size" bytes long. If successful, exactly // this many bytes will have been consumed from the input. boolParseFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); // Like ParseFromBoundedZeroCopyStream(), but accepts messages that are // missing required fields. boolParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); // Parses a protocol buffer contained in a string. Returns true on success. // This function takes a string in the (non-human-readable) binary wire // format, matching the encoding output by MessageLite::SerializeToString(). // If you'd like to convert a human-readable string into a protocol buffer // object, see google::protobuf::TextFormat::ParseFromString(). boolParseFromString(conststring& data); // Like ParseFromString(), but accepts messages that are missing // required fields. boolParsePartialFromString(conststring& data); // Parse a protocol buffer contained in an array of bytes. boolParseFromArray(constvoid* data, int size); // Like ParseFromArray(), but accepts messages that are missing // required fields. boolParsePartialFromArray(constvoid* data, int size);
// Reads a protocol buffer from the stream and merges it into this // Message. Singular fields read from the input overwrite what is // already in the Message and repeated fields are appended to those // already present. // // It is the responsibility of the caller to call input->LastTagWas() // (for groups) or input->ConsumedEntireMessage() (for non-groups) after // this returns to verify that the message's end was delimited correctly. // // ParsefromCodedStream() is implemented as Clear() followed by // MergeFromCodedStream(). boolMergeFromCodedStream(io::CodedInputStream* input);
// Like MergeFromCodedStream(), but succeeds even if required fields are // missing in the input. // // MergeFromCodedStream() is just implemented as MergePartialFromCodedStream() // followed by IsInitialized(). virtual boolMergePartialFromCodedStream(io::CodedInputStream* input) = 0;
// Serialization --------------------------------------------------- // Methods for serializing in protocol buffer format. Most of these // are just simple wrappers around ByteSize() and SerializeWithCachedSizes().
// Write a protocol buffer of this message to the given output. Returns // false on a write error. If the message is missing required fields, // this may GOOGLE_CHECK-fail. boolSerializeToCodedStream(io::CodedOutputStream* output)const; // Like SerializeToCodedStream(), but allows missing required fields. boolSerializePartialToCodedStream(io::CodedOutputStream* output)const; // Write the message to the given zero-copy output stream. All required // fields must be set. boolSerializeToZeroCopyStream(io::ZeroCopyOutputStream* output)const; // Like SerializeToZeroCopyStream(), but allows missing required fields. boolSerializePartialToZeroCopyStream(io::ZeroCopyOutputStream* output)const; // Serialize the message and store it in the given string. All required // fields must be set. boolSerializeToString(string* output)const; // Like SerializeToString(), but allows missing required fields. boolSerializePartialToString(string* output)const; // Serialize the message and store it in the given byte array. All required // fields must be set. boolSerializeToArray(void* data, int size)const; // Like SerializeToArray(), but allows missing required fields. boolSerializePartialToArray(void* data, int size)const;
// This function fills in a Person message based on user input. voidPromptForAddress(tutorial::Person* person){ cout << "Enter person ID number: "; int id; cin >> id; person->set_id(id);//直接调用set方法设置id cin.ignore(256, '\n');
cout << "Enter email address (blank for none): "; string email; getline(cin, email); if (!email.empty()) { person->set_email(email);//这里也是字符串的赋值,但是用的set方法,email临时变量,不懂string类型。还是不要用了 }
while (true) { cout << "Enter a phone number (or leave blank to finish): "; string number; getline(cin, number); if (number.empty()) { break; } //person里面的repeated修饰的phone_number 需要先add 然后set //需要定义一个tutorial::Person::PhoneNumber指针类型 因为person的add函数返回的是该类型的指针,在这个指针上set就改变了person里面的number tutorial::Person::PhoneNumber* phone_number = person->add_phones(); phone_number->set_number(number);
cout << "Is this a mobile, home, or work phone? "; string type; getline(cin, type); if (type == "mobile") { phone_number->set_type(tutorial::Person::MOBILE);//枚举类型使用 } elseif (type == "home") { phone_number->set_type(tutorial::Person::HOME); } elseif (type == "work") { phone_number->set_type(tutorial::Person::WORK); } else { cout << "Unknown phone type. Using default." << endl; } } }
// Main function: Reads the entire address book from a file, // adds one person based on user input, then writes it back out to the same // file. intmain(int argc, char* argv[]){ // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION;
{ // Read the existing address book. fstream input(argv[1], ios::in | ios::binary); if (!input) { cout << argv[1] << ": File not found. Creating a new file." << endl; } elseif (!address_book.ParseFromIstream(&input)) { cerr << "Failed to parse address book." << endl; return-1; } }
// Add an address. 调用add函数添加一个people PromptForAddress(address_book.add_people());
{ // Write the new address book back to disk. fstream output(argv[1], ios::out | ios::trunc | ios::binary); //序列化 if (!address_book.SerializeToOstream(&output)) { cerr << "Failed to write address book." << endl; return-1; } }
// Optional: Delete all global objects allocated by libprotobuf. google::protobuf::ShutdownProtobufLibrary();
// Iterates though all people in the AddressBook and prints info about them. voidListPeople(const tutorial::AddressBook& address_book){ //获取people元素的数量 for (int i = 0; i < address_book.people_size(); i++) { //因为是repeated修饰符 因此定义一个tutorial::Person& person类型,获取元素个数 //&是一个引用,也就是变量的别名。参考 https://blog.csdn.net/qq_25814297/article/details/103829775 const tutorial::Person& person = address_book.people(i); //获取id cout << "Person ID: " << person.id() << endl; //获取字符类型的name 和获取id一样 cout << " Name: " << person.name() << endl; if (person.has_email()) { cout << " E-mail address: " << person.email() << endl; } //同样PhoneNumber是 repeated修饰符 for (int j = 0; j < person.phones_size(); j++) { const tutorial::Person::PhoneNumber& phone_number = person.phones(j);
switch (phone_number.type()) { case tutorial::Person::MOBILE: cout << " Mobile phone #: "; break; case tutorial::Person::HOME: cout << " Home phone #: "; break; case tutorial::Person::WORK: cout << " Work phone #: "; break; } cout << phone_number.number() << endl; } } }
// Main function: Reads the entire address book from a file and prints all // the information inside. intmain(int argc, char* argv[]){ // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION;