C++实用工具类-ini配置文件解析-创新互联

dcc084fe-a937-4cf6-9b2d-f59765a1db19
ini配置文件介绍

一种常见的kv结构的配置文件

专注于为中小企业提供成都做网站、网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业路北免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

主要格式为 key=value

同时支持section, kv归属于一个section 如:

[default]

key1=value1

key2=value2

[section2]

key1=value1

key2=value2

注释, 支持#作为注释开始标记, 本实现仅支持 #单独一行的情况

实现方式

解析文件后按照状态流转进行读取, 如下:

全部读取文件内容到内存后, 按照状态流转一次循环全部字符完成解析,解析内容存放成2级map结构

section-->IniSection

IniSection内部存放 key->value map

并对外提供查询value接口

实现代码

代码目录:

IniConfig.h

#ifndef __INICONFIG_H__
#define __INICONFIG_H__

#include#include#include "IniSection.h"

class IniConfig
{
public:
    IniConfig();

    ~IniConfig();

    bool LoadFile(const std::string& iniFilePath);

    std::string GetValue(const std::string& secName, const std::string& key);

    int GetIntValue(const std::string& secName, const std::string& key);

private:
    std::mapconfigMap_;
};

#endif

IniConfig.cpp

#include "IniConfig.h"
#include#include#includeusing namespace std;

IniConfig::IniConfig()
{
}

IniConfig::~IniConfig()
{
}

enum class IniStat : int
{
    Start, //开始
    Section, //读取section部分
    Key, //读取key
    Value, //读取value
    Comment //注释
};

bool IniConfig::LoadFile(const string& iniFilePath)
{
    fstream fs;
    fs.open(iniFilePath, ios::in);
    if(!fs.is_open())
    {
        return false;
    }

    fs.seekg(0, ios::end);
    int length = fs.tellg();
    fs.seekg(0, ios::beg);

    char* buffer = new char[length+1];
    std::unique_ptrbufferPtr(buffer);
    memset(buffer, 0, length+1);
    fs.read(buffer, length);
    
    IniStat stat = IniStat::Start;
    int pos = 0;
    string key;
    string value;
    IniSection iniSection;
    while(pos< length)
    {
        if(buffer[pos] == '[')
        {
            stat = IniStat::Section;
            configMap_.insert(make_pair(iniSection.sectionName_, iniSection));
            iniSection.Clear();
        }
        else if(stat == IniStat::Section)
        {
            if(buffer[pos] == ']')
            {
                stat = IniStat::Key;
            }
            else
            {
                iniSection.sectionName_ += buffer[pos];
            }
        }
        else if(buffer[pos] == '=')
        {
            stat = IniStat::Value;
        }
        else if(buffer[pos] == '\r' || buffer[pos] == '\n')
        {
            if(!key.empty())
            {
                iniSection.InsertItem(key, value);
                key.clear();
                value.clear();
            }
            stat = IniStat::Key;
        }
        else if(buffer[pos] == '#')
        {
            stat = IniStat::Comment;
        }
        else if(stat == IniStat::Key)
        {
            key += buffer[pos];
        }
        else if(stat == IniStat::Value)
        {
            value += buffer[pos];
        }
        pos++;
    }

    //最后没有换行的情况
    if(!key.empty())
    {
        iniSection.InsertItem(key, value);
    }

    if(!iniSection.Empty())
    {
        configMap_.insert(make_pair(iniSection.sectionName_, iniSection));
    }

    return true;
}

std::string IniConfig::GetValue(const std::string& secName, const std::string& key)
{
    auto itSection = configMap_.find(secName);
    if(itSection != configMap_.end())
    {
        return itSection->second.GetValue(key);
    }
    return "";
}

int IniConfig::GetIntValue(const std::string& secName, const std::string& key)
{
    string value = GetValue(secName, key);
    return atoi(value.c_str());
}

IniSection.h

#ifndef  __INISECTION_H__
#define __INISECTION_H__

#include#includeclass IniSection
{
public:
    IniSection();

    ~IniSection();

    bool Empty() const;

    void Clear();

    void InsertItem(const std::string& key, const std::string& value);

    std::string GetValue(const std::string& key);

    std::string sectionName_;
private:
    std::mapitemMap_;

};

#endif

IniSection.cpp

#include "IniSection.h"

IniSection::IniSection()
{  
}

IniSection::~IniSection()
{
}

void IniSection::Clear()
{
    sectionName_.clear();
    itemMap_.clear();
}

bool IniSection::Empty() const
{
    return sectionName_.empty();
}

void IniSection::InsertItem(const std::string& key, const std::string& value)
{
    itemMap_.insert(make_pair(key, value));
}

std::string IniSection::GetValue(const std::string& key)
{
    auto it = itemMap_.find(key);
    if(it != itemMap_.end())
    {
        return it->second;
    }
    return "";
}

测试代码:

#include "gtest.h"
#include "IniConfig.h"
#includeusing namespace std;

class IniConfigTest : public ::testing::Test
{
};

TEST_F(IniConfigTest, TestSimple)
{
    IniConfig iniConfig;
    if(!iniConfig.LoadFile("./src/unittest/test.ini"))
    {
        GTEST_FAIL();
        return;
    }

    EXPECT_TRUE(iniConfig.GetValue("default","app_name") == "IniConfigTest");
    cout<< "default.app_name="<< iniConfig.GetValue("default","app_name")<< endl;

    EXPECT_TRUE(iniConfig.GetValue("default","testkey3") == "testvalue3");
    cout<< "default.testkey3="<< iniConfig.GetValue("default","testkey3")<< endl;
    
    EXPECT_TRUE(iniConfig.GetIntValue("default","testkey4") == 200);

    string section1_app_name = iniConfig.GetValue("section1","app_name");
    cout<< "section1.app_name="<< section1_app_name<< endl;
    EXPECT_TRUE(section1_app_name == "section1_IniConfigTest");
}

测试用ini文件

[default]
#test comment
app_name=IniConfigTest
testkey1=testvalue1
#test comment
testkey2=testvalue2
#test comment
testkey3=testvalue3
testkey4=200

[section1]
app_name=section1_IniConfigTest
testkey1=section1_testvalue1
testkey2=section1_testvalue2
testkey3=section1_testvalue3
testkey4=section1_200

运行效果:

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


分享标题:C++实用工具类-ini配置文件解析-创新互联
网站地址:http://hbruida.cn/article/dgodgd.html