开发环境及功能
开发环境:linux
开发语言:C++
编译工具:g++、cmake
调试:gdb
目的:使用C++实现一个读取配置文件的工具类,目的是读取key=value形式的配置,提高代码灵活性,解耦合。
实现
- .
- ├── CMakeLists.txt
- ├── config.ini
- ├── include
- │ └── ConfigReader.h
- ├── main.cpp
- └── src
- └── ConfigReader.cpp
复制代码 代码实现
- #pragma once
- #include <string>
- #include <stdexcept>
- #include <map>
- #include <unordered_map>
- class ConfigReader{
- public:
- //explicit 禁用隐式调用,使用时,必须显示的调用
- explicit ConfigReader(const std::string& fileName);
- // const std::string &key 表示不会对key进行修改,不会修改传入的参数值 &避免拷贝
- // const 表示是一个常量成员函数,不会修改类的任何成员变量
- std::string getString(const std::string &key) const;
- int getInt(const std::string &key) const;
- double getDouble(const std::string &key) const;
- bool getBool(const std::string &key) const;
- private:
- //存放解析结果、
- //map 使用红黑树实现,键唯一,插入的键值对会按键的升序排序,查找、插入、删除速度为O(logn)
- //unordered_map使用hash表实现,键唯一,无序,平局查找、插入、删除时间复杂度为O(1),最坏o(n),占内存更多(维护hash表)
- //multimap使用红黑树实现,可以键重复,按键升序排列,查找、插入、删除速度为O(logn)
- std::unordered_map<std::string,std::string> configMap;
- //去除字符串空白字符
- static std::string trim(const std::string & str);
- //解析配置文件
- void parseFile(const std::string &fileName);
- };
复制代码- #include "ConfigReader.h"
- #include <fstream>
- ConfigReader::ConfigReader(const std::string &fileName){
- parseFile(fileName);
- }
- //把所有非注释的行添加到map结构中
- void ConfigReader::parseFile(const std::string &fileName){
- std::ifstream file(fileName);
- if(!file.is_open()){
- throw std::runtime_error("Failed to open config file:"+fileName);
- }
- std::string line;
- while(std::getline(file,line)){
- //获取第一个#或/的位置
- size_t commentPos = line.find_first_of("#/");
- //如果该行有#或者/,则认为改行为注释行
- if(std::string::npos != commentPos){
- continue;
- }
- size_t equalPos = line.find('=') != std::string::npos ? line.find('=') : line.find(':');
- if(std::string::npos == equalPos){
- continue;
- }
- std::string key = trim(line.substr(0,equalPos));
- std::string value = trim(line.substr(equalPos+1));
- if(!key.empty()){
- configMap[key] = value;
- }
- }
- }
- //处理字符串首尾的空格
- std::string ConfigReader::trim(const std::string& str){
- if(str.empty()) return str;
- auto start = str.begin();
- while(start != str.end() && std::isspace(*start)){
- start++;
- }
- auto end = str.end();
- do{
- end--;
- }while(std::distance(start,end)>0 && std::isspace(*end));
- return std::string(start,end+1);
- }
- std::string ConfigReader::getString(const std::string & key) const{
- auto it = configMap.find(key);
- if(it == configMap.end()){
- throw std::out_of_range("config key not found:"+key);
- }
- return it->second;
- }
- int ConfigReader::getInt(const std::string & key) const{
- std::string value = getString(key);
- try{
- return std::stoi(value);
- }
- catch(const std::exception & e){
- throw std::runtime_error("Invalid integer value for key"+key+":"+value);
- }
- }
- }
- return it->second;
- }
- double ConfigReader::getDouble(const std::string & key) const{
- std::string value = getString(key);
- try{
- return std::stod(value);
- }
- catch(const std::exception & e){
- throw std::runtime_error("Invalid double value for key"+key+":"+value);
- }
- }
- bool ConfigReader::getBool(const std::string & key) const{
- std::string value = getString(key);
- try{
- if(value == "true")
- return true;
- else if(value == "false")
- return false;
- }
- catch(const std::exception & e){
- throw std::runtime_error("Invalid integer value for key"+key+":"+value);
- }
- }
复制代码 [code]#include #include "ConfigReader.h"int main() { try { ConfigReader config("config.ini"); std::string ip = config.getString("server_ip"); int port = config.getInt("server_port"); double timeout = config.getDouble("timeout"); bool debug = config.getBool("debug_mode"); std::string log_path = config.getString("log_path"); std::cout |