linux下使用protobuf实现简单配置功能 - Go语言中文社区

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



前言:

    程序一般需要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做成一个简单的配置管理库了


文件定义test.proto:

message student{
    required string name = 1;   //姓名
    required int32  age = 2;    //年龄
    optional string addr = 3;
}

//班级
message class{
    required string name = 1;   //班级名称
    repeated student member = 2;    //班级成员

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


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

name: "Communication 2004"
member {
  name: "flyan338"
  age: 26
  addr: "china"
}
member {
  name: "likeliu"
  age: 25
  addr: "china"
}
member {
  name: "gaoy"
  age: 24
  addr: "American"
}

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

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

#include <test.pb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fcntl.h>
#include <fstream>
#include <cstdio>
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>

using namespace std;
int main(int argc, char** argv){
    if (argc <2){
        printf("programe savefilen");
        exit(1);
    }

    //声明一个class结构
    classes c;
    c.set_name("Communication 2004");
    //添加学生
    student* t = c.add_member();
    t->set_name("flyan338");
    t->set_age(26);
    t->set_addr("china");
    
    t = c.add_member();
    t->set_name("likeliu");
    t->set_age(25);
    t->set_addr("china");
 
    t = c.add_member();
    t->set_name("gaoy");
    t->set_age(24);
    t->set_addr("American");


    //首先将protobuf输出到一个string中
    std::string p;
    google::protobuf::TextFormat::PrintToString(c,&p);
    
    //输出到文件中
    ofstream fout;
    fout.open(argv[1], ios::out| ios_base::ate);
    if (!fout.is_open()){
        fprintf(stderr, "open %s failn", argv[1]);
        return -1;
    }
    fout <<p<<endl;
    fout.flush();
    fout.close();

    return 0;
}

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

 

解析的代码更简单:

#include <test.pb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <fcntl.h>
#include <fstream>
#include <cstdio>
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>

using namespace std;
int main(int argc, char** argv){
    if (argc <2){
        printf("programe reloadfilen");
        exit(1);
    }

    classes c;
    int fileDescriptor = open(argv[1], O_RDONLY);
    if( fileDescriptor < 0 ){
        return -1;
    }
    google::protobuf::io::FileInputStream fileInput(fileDescriptor);
    fileInput.SetCloseOnDelete( true );
    if (!google::protobuf::TextFormat::Parse(&fileInput, &c)){
        return -2;
    }
    cout<<"classes name:" <<c.name() <<endl;
    cout<<"student number:"<<c.member_size()<<endl;
    for (int i = 0 ; i < c.member_size(); i++){
        cout <<"student name:"<<c.member(i).name()<<endl;
        cout <<"student age:" << c.member(i).age()<<endl;
        cout <<"student addr:" << c.member(i).addr() <<endl;
    }
    return 0;
}



程序运行的截图为:


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

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

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


版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/flyan338/article/details/8448518
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-05-07 22:39:57
  • 阅读 ( 988 )
  • 分类:Linux

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢