linux下使用protobuf实现简单配置功能

http://blog.csdn.net/flyan338/article/details/8448518

前言:

    程序一般需要load一些参数列表,一般来说我们可以通过linux自带的命令行解析函数来搞定(getopt_long,如果需要了解的man一 下,manpage里面是有example的),但是对于参数太多,我们不可能写满一屏幕进行传参吧,当然,我们的输入在linux里面也是有限制的。所以呢,一般的做法是load一个配置文件,进行解析;最近在研究了一下protobuf的使用,我们都知道protobuf在网络中作为协议发送比较爽,但是发现用protobuf来实现程序的配置文件管理也是一个 不错的思路。

 

protobuf是何物?

大名鼎鼎的google公司的开源软件,被N多程序员推荐使用,个人认为优点是:

1:api接口很友好,这点很重要

2:serilize之后的包比较小,速度快,这个在网络传输中至关重要

3:可扩展性强,加入和删除字段都是透明的。这个在互联网开发中,经常变更协议的时候十分重要

不过protobuf持久化的东西是一个二进制,基本不可读(可以参考https://developers.google.com/protocol-buffers/docs/overview?hl=zh-CN)

不过最近看到了一个protobuf的接口google::protobuf::TextFormat,发现protobuf支持文本的输出,这样我们就能将protobuf做成一个简单的配置管理库了


[plain]  view plain copy
  1. 文件定义test.proto:  

[plain]  view plain copy
  1. message student{  
  2.     required string name = 1;   //姓名  
  3.     required int32  age = 2;    //年龄  
  4.     optional string addr = 3;  
  5. }  
  6.   
  7. //班级  
  8. message class{  
  9.     required string name = 1;   //班级名称  
  10.     repeated student member = 2;    //班级成员  

protoc --cpp_out=.test.proto  可以生成test.pb.htest.pb.cc这两个文件


在写程序运行之前,我们直观的看一下protobuf的TextFormat格式是什么样子的吧:

[plain]  view plain copy
  1. name: "Communication 2004"  
  2. member {  
  3.   name: "flyan338"  
  4.   age: 26  
  5.   addr: "china"  
  6. }  
  7. member {  
  8.   name: "likeliu"  
  9.   age: 25  
  10.   addr: "china"  
  11. }  
  12. member {  
  13.   name: "gaoy"  
  14.   age: 24  
  15.   addr: "American"  
  16. }  

这份配置表明:一个叫做 "Communication 2004"的班级,有3个student,你可以直接用protobuf来load出来

这份文件怎么生成的呢?代码如下:

[cpp]  view plain copy
  1. #include <test.pb.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4. #include <string.h>  
  5. #include <iostream>  
  6. #include <fcntl.h>  
  7. #include <fstream>  
  8. #include <cstdio>  
  9. #include <google/protobuf/text_format.h>  
  10. #include <google/protobuf/io/zero_copy_stream_impl.h>  
  11.   
  12. using namespace std;  
  13. int main(int argc, char** argv){  
  14.     if (argc <2){  
  15.         printf("programe savefile\n");  
  16.         exit(1);  
  17.     }  
  18.   
  19.     //声明一个class结构  
  20.     classes c;  
  21.     c.set_name("Communication 2004");  
  22.     //添加学生  
  23.     student* t = c.add_member();  
  24.     t->set_name("flyan338");  
  25.     t->set_age(26);  
  26.     t->set_addr("china");  
  27.       
  28.     t = c.add_member();  
  29.     t->set_name("likeliu");  
  30.     t->set_age(25);  
  31.     t->set_addr("china");  
  32.    
  33.     t = c.add_member();  
  34.     t->set_name("gaoy");  
  35.     t->set_age(24);  
  36.     t->set_addr("American");  
  37.   
  38.   
  39.     //首先将protobuf输出到一个string中  
  40.     std::string p;  
  41.     google::protobuf::TextFormat::PrintToString(c,&p);  
  42.       
  43.     //输出到文件中  
  44.     ofstream fout;  
  45.     fout.open(argv[1], ios::out| ios_base::ate);  
  46.     if (!fout.is_open()){  
  47.         fprintf(stderr, "open %s fail\n", argv[1]);  
  48.         return -1;  
  49.     }  
  50.     fout <<p<<endl;  
  51.     fout.flush();  
  52.     fout.close();  
  53.   
  54.     return 0;  
  55. }  

只是简单的进行一些set操作,就可以生成这样的配置文件

 

解析的代码更简单:

[cpp]  view plain copy
  1. #include <test.pb.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4. #include <string.h>  
  5. #include <iostream>  
  6. #include <fcntl.h>  
  7. #include <fstream>  
  8. #include <cstdio>  
  9. #include <google/protobuf/text_format.h>  
  10. #include <google/protobuf/io/zero_copy_stream_impl.h>  
  11.   
  12. using namespace std;  
  13. int main(int argc, char** argv){  
  14.     if (argc <2){  
  15.         printf("programe reloadfile\n");  
  16.         exit(1);  
  17.     }  
  18.   
  19.     classes c;  
  20.     int fileDescriptor = open(argv[1], O_RDONLY);  
  21.     if( fileDescriptor < 0 ){  
  22.         return -1;  
  23.     }  
  24.     google::protobuf::io::FileInputStream fileInput(fileDescriptor);  
  25.     fileInput.SetCloseOnDelete( true );  
  26.     if (!google::protobuf::TextFormat::Parse(&fileInput, &c)){  
  27.         return -2;  
  28.     }  
  29.     cout<<"classes name:" <<c.name() <<endl;  
  30.     cout<<"student number:"<<c.member_size()<<endl;  
  31.     for (int i = 0 ; i < c.member_size(); i++){  
  32.         cout <<"student name:"<<c.member(i).name()<<endl;  
  33.         cout <<"student age:" << c.member(i).age()<<endl;  
  34.         cout <<"student addr:" << c.member(i).addr() <<endl;  
  35.     }  
  36.     return 0;  
  37. }  


程序运行的截图为:


这样一个基于protobuf的配置搞定:

以后程序员可以自定义一个proto文件,然后要么按照特定的格式填写save_file,要么直接写程序生成一个save_file,

有了这个save_file,只需要load一下就搞定了,然后可以很方便的使用protobuf内置的各种函数,个人觉得是个不错的选择



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值