1,工程
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7aeb0507c448b4d622dd720dad4e07cb.png)
1.1,消息结构体— addressbook.proto
syntax = "proto2";
package tutorial;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phones = 4;
}
message AddressBook {
repeated Person people = 1;
}
1.2,文本格式prototxt 文件 — txt.prototxt
people{
name: "123"
id: 1
email: "222"
phones{
number: "12334332"
type: HOME
}
}
1.3,操作接口定义 — protobuf.h
#ifndef __PROTOBUF_H__
#define __PROTOBUF_H__
#include <iostream>
#include <fstream>
#include <string>
#include <fcntl.h>
#include <unistd.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/text_format.h>
#include <limits>
#include "proto/addressbook.pb.h"
template <typename T> class Protobuf {
private:
public:
Protobuf();
~Protobuf();
bool readProtoFromTextFile(const char* filename, T* proto);
bool readProtoFromBinaryFile(const char* filename, T* proto);
bool writeProtoToBinaryFile(const char* filename, T* proto);
bool readProtoFromString(std::string &buff, T* proto);
bool writeProtoToString(std::string &buff, T* proto);
void printList(const T &address_book);
void PromptForAddress(tutorial::Person *person);
};
#endif
1.4,操作接口实现及测试代码 — protobuf.cpp
#include "protobuf.h"
template <typename T> Protobuf<T>::Protobuf()
{
GOOGLE_PROTOBUF_VERIFY_VERSION;
}
template <typename T> Protobuf<T>::~Protobuf() {
google::protobuf::ShutdownProtobufLibrary();
}
template <typename T> bool Protobuf<T>::readProtoFromTextFile(const char*
filename, T* proto) {
int fd = open(filename, O_RDONLY);
google::protobuf::io::FileInputStream* input = (
new google::protobuf::io::FileInputStream(fd));
bool success = google::protobuf::TextFormat::Parse(input, proto);
delete input;
close(fd);
return success;
}
template <typename T> bool Protobuf<T>::readProtoFromBinaryFile(const char*
filename, T* proto) {
std::ifstream model_file(filename);
return proto->ParseFromIstream(&model_file);
}
template <typename T> bool Protobuf<T>::writeProtoToBinaryFile(const char*
filename, T* proto) {
std::fstream model_file(filename,std::ios::out |std::ios::trunc |std::ios::binary);
return proto->SerializeToOstream(&model_file);
}
template <typename T> bool Protobuf<T>::readProtoFromString(std::string &buff,
T* proto) {
return proto->ParseFromString(buff);
}
template <typename T> bool Protobuf<T>::writeProtoToString(std::string &buff, T* proto) {
return proto->SerializeToString(&buff);
}
template <typename T> void Protobuf<T>::printList(const T &address_book) {
for (int i = 0; i < address_book.people_size(); i++) {
const tutorial::Person &person = address_book.people(i);
std::cout << "Person ID: " << person.id() << std::endl;
std::cout << " Name: " << person.name() << std::endl;
if (person.has_email()) {
std::cout << " E-mail address: " << person.email() << std::endl;
}
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:
std::cout << " Mobile phone #: ";
break;
case tutorial::Person::HOME:
std::cout << " Home phone #: ";
break;
case tutorial::Person::WORK:
std::cout << " Work phone #: ";
break;
}
std::cout << phone_number.number() << std::endl;
}
}
}
template <typename T> void Protobuf<T>::PromptForAddress(tutorial::Person *person) {
std::cout << "Enter person ID number: ";
int id;
std::cin >> id;
person->set_id(id);
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cout << "Enter name: ";
getline(std::cin, *person->mutable_name());
std::cout << "Enter email address (blank for none): ";
std::string email;
getline(std::cin, email);
if (!email.empty()) {
person->set_email(email);
}
while (true) {
std::cout << "Enter a phone number (or leave blank to finish): ";
std::string number;
getline(std::cin, number);
if (number.empty()) {
break;
}
tutorial::Person::PhoneNumber *phone_number = person->add_phones();
phone_number->set_number(number);
std::cout << "Is this a mobile, home, or work phone? ";
std::string type;
getline(std::cin, type);
if (type == "mobile") {
phone_number->set_type(tutorial::Person::MOBILE);
} else if (type == "home") {
phone_number->set_type(tutorial::Person::HOME);
} else if (type == "work") {
phone_number->set_type(tutorial::Person::WORK);
} else {
std::cout << "Unknown phone type. Using default." << std::endl;
}
}
}
int main(int argc, char *argv[]) {
char *file_name = "proto/txt.prototxt";
char file_name_2[] = "binary.prototxt";
Protobuf<tutorial::AddressBook> pro;
tutorial::AddressBook address_book;
tutorial::AddressBook address_book_2;
tutorial::AddressBook address_book_3;
tutorial::AddressBook address_book_4;
if (argc != 2) {
std::cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << std::endl;
printf(" use dafaule address_book_file: %s\n", file_name);
}
else {
file_name = argv[1];
}
std::cout << "/************read txt file***********************/" << std::endl;
if(!pro.readProtoFromTextFile(file_name, &address_book))
{
std::cout<<"error opening train_val file"<<std::endl;
return -1;
}
pro.printList(address_book);
std::cout << "/***********add people and write binary file*****/" << std::endl;
pro.readProtoFromBinaryFile(file_name_2, &address_book_2);
pro.PromptForAddress(address_book_2.add_people());
pro.printList(address_book_2);
pro.writeProtoToBinaryFile(file_name_2, &address_book_2);
std::cout << "/************read binary file********************/" << std::endl;
if(!pro.readProtoFromBinaryFile(file_name_2, &address_book_3))
{
std::cout<<"error opening train_val file"<<std::endl;
return -1;
}
pro.printList(address_book_3);
std::cout << "/*************write-read string file*************/" << std::endl;
std::string buff;
pro.writeProtoToString(buff, &address_book_3);
pro.readProtoFromString(buff, &address_book_4);
pro.printList(address_book_4);
return 0;
}
1.5,Makefile
PROTO_FILE=addressbook
PROTO_SRC_DIR=./proto
PROTO_DST_DIR=./proto
cpp_out:
if [ ! -d $(PROTO_DST_DIR) ];then mkdir -p $(PROTO_DST_DIR); fi
protoc -I=$(PROTO_SRC_DIR) --cpp_out=$(PROTO_DST_DIR) $(PROTO_SRC_DIR)/$(PROTO_FILE).proto
CXX=g++
LDFLAGS=-std=c++11 -O1 -g -w -fopenmp
CFLAGS = -lprotobuf
LIBS=`pkg-config --cflags --libs protobuf`
TARGET=protobuf.app
SRC=protobuf.cpp
SRCS=$(PROTO_SRC_DIR)/$(PROTO_FILE).pb.cc $(SRC)
run:
@echo "Compilling......"
$(CXX) $(LDFLAGS) $(SRCS) -o $(TARGET) $(CFLAGS) $(LIBS)
.PHONY:clean
clean:
rm -rf $(TARGET) $(PROTO_DST_DIR)/*.pb.cc $(PROTO_DST_DIR)/*pb.h *.prototxt
2,编译测试
2.1,生成访问类
make cpp_out
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c77b57fb90687beb13b888530df17eab.png)
2.2,编译工程,生成可执行文件
make run
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/9e8f2630c921212587f3b39ddb14eeee.png)
2.3,测试
./protobuf
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b86ec0558a4db88fc1c18f101773c1d4.png)