1.在当前文件夹内新建addressbook.proto,并输入:
package ContactInfo;
message Person
{
required string curName = 1;
required int32 curId = 2;
optional string curEmail = 3;
enum PhoneType
{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber
{
required string number = 4;
optional PhoneType type = 2[default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook
{
required string owner = 10;
repeated Person personInfo = 6;
}
2.将终端定位到当前文件夹,并输入:
protoc --cpp_out=./ addressbook.proto
说明:
a.如果希望生成的.h和.cpp都在当前文件夹,则--cpp_out=./即可。
b.如果使用如下命令:
protoc -I=src --cpp_out=dst src/ addressbook.proto
则addressbook.proto在当前文件夹的src文件夹里,生成的.h和.cpp均位于当前文件夹下的dst文件夹下面。
c.生成的头文件中,ContactInfo为命名空间,里面包含Person、PhoneNumber、AddressBook三个类。枚举类型则看该类型所在的类,使用作用域限定符来访问,如:
ContactInfo::Person::MOBILE
3.在生成的.h和.cpp文件所在的文件夹内,新建testAddBook.cpp,并输入:
#include "addressbook.pb.h"
#include <fstream>
#include <iostream>
using namespace std;
/////////////////////////////////////////////////////////////////////////////////
int saveAddInfo()
{
ContactInfo::AddressBook addbook;
addbook.set_owner("xxx");
// first person
ContactInfo::Person* pperson = addbook.add_personinfo();
pperson->set_curname("aaa");
pperson->set_curid(25);
pperson->set_curemail("aaa@126.com");
ContactInfo::Person_PhoneNumber* pPhoneNum = pperson->add_phone();
pPhoneNum->set_number("111111111");
pPhoneNum->set_type(ContactInfo::Person::HOME);
pPhoneNum = pperson->add_phone();
pPhoneNum->set_number("222222222");
pPhoneNum->set_type(ContactInfo::Person::MOBILE);
// second person
pperson = addbook.add_personinfo();
pperson->set_curname("bbb");
pperson->set_curid(30);
// pperson->set_curemail("bbb@126.com");
pPhoneNum = pperson->add_phone();
pPhoneNum->set_number("333333333");
// pPhoneNum->set_type(ContactInfo::Person::HOME);
pPhoneNum = pperson->add_phone();
pPhoneNum->set_number("444444444");
pPhoneNum->set_type(ContactInfo::Person::MOBILE);
// int length = addbook.ByteSize();
// char* buf = new char[length]; // serialize to char*, and transmit by net or others
// addbook.SerializeToArray(buf,length);
fstream output("pbinfo.log", ios::out|ios::trunc|ios::binary);
if(!addbook.SerializeToOstream(&output))
{
cerr << "fail to write msg" << endl;
//delete[] buf;
return -1;
}
//delete[] buf;
return 0;
}
////////////////////////////////////////////////////////////////////////////
void showMsg(const ContactInfo::AddressBook& addbook)
{
cout << addbook.owner() << endl;
for (int i = 0; i < addbook.personinfo_size(); ++i)
{
cout << addbook.personinfo(i).curname() << endl;
cout << addbook.personinfo(i).curid() << endl;
if(addbook.personinfo(i).has_curemail())
cout << addbook.personinfo(i).curemail() << endl;
else
cout << "no email" << endl;
for (int j = 0; j < addbook.personinfo(i).phone_size(); ++j)
{
cout<<addbook.personinfo(i).phone(j).number() << endl;
if(addbook.personinfo(i).phone(j).has_type())
cout << addbook.personinfo(i).phone(j).type() << endl;
else
cout << "no phone type" << endl;
}
}
}
void showMsgbyAuto(ContactInfo::AddressBook addbook)
{
cout << addbook.owner() << endl;
auto pperson = addbook.mutable_personinfo();
for (auto it = pperson->begin(); it != pperson->end(); ++it)
{
cout << it->curname() << endl;
cout << it->curid() << endl;
if(it->has_curemail())
cout << it->curemail() << endl;
else
cout << "no email" << endl;
auto pPhoneNum = it->mutable_phone();
for (auto ij = pPhoneNum->begin(); ij != pPhoneNum->end(); ++ij)
{
cout << ij->number() << endl;
if(ij->has_type())
cout << ij->type() << endl;
else
cout << "no phone type" << endl;
}
}
}
int loadAddInfo()
{
ContactInfo::AddressBook addbook;
fstream input("pbinfo.log", ios::in|ios::binary);
if(!addbook.ParseFromIstream(&input))
{
cout << "fail to write msg" << endl;
return -1;
}
cout << "now show msg" << endl;
showMsg(addbook);
cout << endl;
showMsgbyAuto(addbook);
return 0;
}
///////////////////////////////////////////////////////////////////////////////
int main()
{
int choice;
cout << "input choice: 1 for save, 2 for load" << endl;
cin >> choice;
if(1 == choice)
{
saveAddInfo();
}
else if (2 == choice)
{
loadAddInfo();
}
return 0;
}
说明:上面程序使用SerializeToArray后,可以将数据放到buf的缓冲区中,方便使用网络或者其他方式发送。
4.终端定位到testAddBook.cpp所在文件夹,并输入:
g++ -std=c++11 addressbook.pb.cc testAddBook.cpp -o testAddBook -lprotobuf -pthread
说明:
a.上面程序showMsgbyAuto函数使用了C++11特性,因而终端中需要加上-std=c++11;否则可以不加。如果不使用C++11特性,则使用下面的方式访问,但是太长。:
::google::protobuf::RepeatedPtrField< ::ContactInfo::Person >
b.如果protobuf没有安装到/usr路径,而是/usr/local路径,可能需要下面的命令:
c.此处不能使用gcc编译,我这里提示出错了:
/usr/bin/ld: /tmp/ccO3HeHo.o: undefined reference to symbol '_ZNSaIcED1Ev@@GLIBCXX_3.4'
//usr/lib/x86_64-linux-gnu/libstdc++.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
5.终端中输入./testAddBook,之后输入1,会存储pbinfo.log文件。
6.终端中输入./testAddBook,之后输入2,显示如下:
说明解析的文件成功。
说明:对于optional可选项,可以不使用has_xxx()进行判断,此时不输出(程序有endl,所以会输出一个空行)(不知道其他使用方式时,会是什么情况)。