首页 > 代码库 > 简单的INI解析封装

简单的INI解析封装

简单封装的一个ini解析处理类(支持跨平台)。支持功能:

  1. 加载并解析指定ini文件中的配置;
  2. 读取指定 section 下的指定 key 的值。提示:支持按数值型读取,或按文本类型读取;
    使用示例:
    1 auto fWidth         = 480.0f;2 auto fHeight        = 320.0f;3 4 ns_ini::IniParser ini;5 ini.open(strConfigFile.c_str());6 fWidth              = ini.readFloat("glview", "screen_width", fWidth);7 fHeight             = ini.readFloat("glview", "screen_height", fHeight);
  3. 支持新段、项、值写入;提示:如果写入的项是已经存在的,则为修改旧项值;
    示例:
     1 auto fWidth         = 480.0f; 2 auto fHeight        = 320.0f; 3  4 ns_ini::IniParser ini; 5 ini.open(strConfigFile.c_str()); 6 fWidth              = ini.readFloat("glview", "screen_width", fWidth); 7 fHeight             = ini.readFloat("glview", "screen_height", fHeight); 8  9 ini.writeFloat("glview", "screen_height, 777.77f); // 将旧值修改为 777.77f10 ini.writeInt("glview", "screen_height, 666); // 再次将旧值修改为 66611 ini.writeText("glview", "screen_height, "jacc.kim"); // 再次将旧值修改为 文本"jacc.kim"

源码如下:

技术分享
 1 /****************************************************************************** 2  3                              I‘m jacc.kim 4  5     CreateDate: 2017-06-13 17:12:16  6     FileName  : JKIniParser.h 7     Version   : 1.00 8     Author    : jacc.kim 9     Summary   : ini parser wrapper10 11 ******************************************************************************/12 #pragma once13 14 #include <list>15 #include <map>16 17 namespace ns_ini18 {19 20 class Section;21 22 /******************************************************************************23  * create   : (jacc.kim) [06-13-2017]24  * summary  : class IniParser25 ******************************************************************************/26 class IniParser27 {28 public:29     void                                        setIniFile(const char* const pcszIniFile);30     bool                                        open(const char* const pcszIniFile = nullptr);31     bool                                        save(const char* const pcszIniFile = nullptr);32     void                                        close();33 34     unsigned int                                getSectionAmount() const;35     bool                                        isSectionExisted(const char* const pcszSection) const;36     bool                                        isParameterExisted(const char* const pcszSection, const char* const pcszParameter) const;37 38     int                                         readInt(const char* const pcszSection, const char* const pcszKey, const int def = 0) const;39     unsigned int                                readUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int def = 0u) const;40     bool                                        readBool(const char* const pcszSection, const char* const pcszKey, const bool def = false) const;41     float                                       readFloat(const char* const pcszSection, const char* const pcszKey, const float def = 0.0f) const;42     double                                      readDouble(const char* const pcszSection, const char* const pcszKey, const double def = 0.0) const;43     const char*                                 readText(const char* const pcszSection, const char* const pcszKey, const char* const def = nullptr) const;44 45     // !!!note: write existed section & key, the old value will be replaced.46     void                                        writeInt(const char* const pcszSection, const char* const pcszKey, const int value);47     void                                        writeUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int value);48     void                                        writeBool(const char* const pcszSection, const char* const pcszKey, const bool value);49     void                                        writeFloat(const char* const pcszSection, const char* const pcszKey, const float value);50     void                                        writeDouble(const char* const pcszSection, const char* const pcszKey, const double value);51     void                                        writeText(const char* const pcszSection, const char* const pcszKey, const char* const value);52 53     bool                                        remove(const char* const pcszSection, const char* const pcszKey);54     bool                                        remove(const char* const pcszSection);55     void                                        clear();56 57 public:58     IniParser();59     ~IniParser();60 61     Section*                                    getSection(const char* const pcszSection) const;62     Section&                                    operator[](const char* const pcszSection) const;63 64 private:65     IniParser(const IniParser& rhs)/* = delete*/;66     IniParser& operator=(const IniParser& rhs)/* = delete*/;67 68     void                                        trimLeft(char*& p, char*& q);69     void                                        trimRight(char*& p, char*& q);70     void                                        trim(char*& p, char*& q);71     void                                        trimRN0(char*& p, char*& q);72     bool                                        isEndWithN(const char* p, const size_t nLength);73     bool                                        stringEqual(const char* p, const char* q, int nChar = INT_MAX) const;74     bool                                        isSectionName(char* p, char* q);75     char*                                       splitKeyValue(char* p, char* q);76     void                                        parseIniLine(char* szIniLine);77     void                                        addSection(char* szSectionName);78     void                                        addParameter(char* szKey, char* szValue);79 80 private:81     typedef std::list<Section*>                 SectionList;82     typedef SectionList::iterator               SectionListIter;83 84     // key = section name, value = http://www.mamicode.com/section‘s ptr85     typedef std::map <std::string, SectionListIter> SectionMap;86 87 private:88     std::string                                 m_strIniFile;       // ini file name89     SectionList                                 m_listSections;     // all sections.90     SectionMap                                  m_mapSectionName;   // section <--> index mapping.(only reference.)91 92 };//class IniParser93 94 }//namespace ns_ini
IniParser.h 文件
技术分享
  1 #include "JKIniParser.h"  2   3 namespace ns_ini  4 {  5   6 /******************************************************************************  7  * create   : (jacc.kim) [06-13-2017]  8  * summary  : class Section  9 ******************************************************************************/ 10 class Section 11 { 12 public: 13     struct Parameter 14     { 15         std::string                             key; 16         std::string                             value; 17     };//struct Parameter 18  19     typedef std::list<Parameter>                ParameterList; 20     typedef ParameterList::iterator             ParameterListIter; 21     typedef std::map<std::string, ParameterListIter>    ParameterMap; 22  23 public: 24     Section(const char* pcszSectionName) : m_strSectionName  (pcszSectionName) 25                                          , m_listParameters  () 26                                          , m_mapParameterKeys() 27     {} 28  29     ~Section() { 30         this->clear(); 31     } 32  33     const char* getSectionName() const { 34         return m_strSectionName.c_str(); 35     } 36  37     bool isParameterExisted(const char* const pcszKey) const { 38         return m_mapParameterKeys.find(pcszKey) != m_mapParameterKeys.end(); 39     } 40  41     Parameter& operator[](const char* const pcszKey) const { 42         auto iter                               = m_mapParameterKeys.find(pcszKey); 43         return *(iter->second); 44     } 45  46     const char* read(const char* const pcszKey) { 47         const char* pcszRetValue                =http://www.mamicode.com/ nullptr; 48         if (nullptr != pcszKey) { 49             auto iter                           = m_mapParameterKeys.find(pcszKey);; 50             if (m_mapParameterKeys.end() != iter) { 51                 pcszRetValue                    = http://www.mamicode.com/(*(iter->second)).value.c_str(); 52             } 53         } 54         return pcszRetValue; 55     } 56  57     bool write(const char* const pcszKey, const char* const pcszValue) { 58         auto iter = m_mapParameterKeys.find(pcszKey); 59         if (m_mapParameterKeys.end() == iter) { 60             Parameter param = { pcszKey, pcszValue }; 61             m_listParameters.emplace_back(param); 62             m_mapParameterKeys[pcszKey] = --m_listParameters.end(); 63             return true; 64         } 65         (*this)[pcszKey].value                  =http://www.mamicode.com/ pcszValue; 66         return true; 67     } 68  69     bool remove(const char* pcszKey) { 70         auto bIsSuccess                         = false; 71         if (nullptr != pcszKey) { 72             auto iter                           = m_mapParameterKeys.find(pcszKey); 73             if (m_mapParameterKeys.end() != iter) { 74                 m_listParameters.erase(iter->second); 75                 m_mapParameterKeys.erase(iter); 76                 bIsSuccess                      = true; 77             } 78         } 79         return bIsSuccess; 80     } 81  82     void clear() { 83         m_listParameters.clear(); 84         m_mapParameterKeys.clear(); 85     } 86  87     ParameterList& getAllParameters() { 88         return m_listParameters; 89     } 90  91 private: 92     std::string                                 m_strSectionName; 93     ParameterList                               m_listParameters; 94     ParameterMap                                m_mapParameterKeys; 95  96 };//class Section 97  98 /////////////////////////////////////////////////////////////////////////////// 99 // class IniParser100 IniParser::IniParser() : m_strIniFile    ("")101                        , m_listSections  ()102                        , m_mapSectionName()103 {104 105 }106 107 IniParser::~IniParser() {108     this->clear();109 }110 111 void IniParser::setIniFile(const char* const pcszIniFile) {112     if (nullptr == pcszIniFile) {113         return;114     }115     m_strIniFile                    = pcszIniFile;116 }117 118 bool IniParser::open(const char* const pcszIniFile/* = nullptr*/) {119     auto bIsSuccess                 = false;120     const char* pcszOpenFile        = nullptr != pcszIniFile ? pcszIniFile : m_strIniFile.c_str();121     if (nullptr == pcszOpenFile) {122         return bIsSuccess;123     }124     if (nullptr != pcszIniFile) {125         this->setIniFile(pcszIniFile);126     }127     this->clear();128     auto pINIFile                   = fopen(pcszIniFile, "rb");129     if (nullptr != pINIFile) {130         bIsSuccess = true;131         const size_t nBUFF_SIZE     = 2048;132         char szBuff[nBUFF_SIZE];133         while (!feof(pINIFile)) {134             memset((void*)szBuff, 0x0L, nBUFF_SIZE);135             fgets(szBuff, nBUFF_SIZE, pINIFile);136             this->parseIniLine(szBuff);137         }138         fclose(pINIFile);139         pINIFile                    = nullptr;140     }141 142     return bIsSuccess;143 }144 145 bool IniParser::save(const char* const pcszIniFile/* = nullptr*/) {146     auto bIsSuccess                 = false;147     const char* pcszSaveFile        = nullptr != pcszIniFile ? pcszIniFile : m_strIniFile.c_str();148     if (nullptr == pcszSaveFile) {149         return bIsSuccess;  // 没有可保存的路径150     }151     ::remove(pcszSaveFile);152     auto pINIFile                   = fopen(pcszSaveFile, "ab+");153     if (nullptr != pINIFile) {154         bIsSuccess                  = true;155         auto iter                   = m_listSections.begin();156         const auto iterend          = m_listSections.end();157         const size_t nBUFF_SIZE     = 2048;158         char szBuffer[nBUFF_SIZE];159         Section* pSection           = nullptr;160         for (; iterend != iter;/* ++iter*/) {161             pSection                = *iter;162             const char* pcszSectionName = pSection->getSectionName();163             fputs("[", pINIFile);164             fputs(pcszSectionName, pINIFile);165             fputs("]\r\n", pINIFile);166             auto& allParameters     = (*iter)->getAllParameters();167             auto listiter           = allParameters.begin();168             const auto listiterend  = allParameters.end();169             for (; listiterend != listiter; ++listiter) {170                 auto& param         = *listiter;171                 memset((void*)szBuffer, 0x0L, nBUFF_SIZE);172                 memcpy(szBuffer, param.key.c_str(), param.key.length());173                 szBuffer[param.key.length()] = =;174                 memcpy(szBuffer + param.key.length() + 1, param.value.c_str(), param.value.length());175                 const auto nEndPos    = param.key.length() + 1 + param.value.length();176                 szBuffer[nEndPos + 1] = \0;177                 fputs(szBuffer, pINIFile);178                 if (!this->isEndWithN(szBuffer, nEndPos + 1)) {179                     fputs("\r\n", pINIFile);180                 }181             }182             if (iterend != ++iter) {183                 fputs("\r\n", pINIFile);184             }185         }186         fclose(pINIFile);187         pINIFile = nullptr;188     }189 190     return bIsSuccess;191 }192 193 void IniParser::close() {194     this->save();195     this->clear();196     this->setIniFile(nullptr);197 }198 199 unsigned int IniParser::getSectionAmount() const {200     return static_cast<unsigned int>(m_listSections.size());201 }202 203 bool IniParser::isSectionExisted(const char* const pcszSection) const {204     return nullptr != this->getSection(pcszSection);205 }206 207 bool IniParser::isParameterExisted(const char* const pcszSection, const char* const pcszParameter) const {208     auto pSection = this->getSection(pcszSection);209     return nullptr != pSection && pSection->isParameterExisted(pcszParameter);210 }211 212 int IniParser::readInt(const char* const pcszSection, const char* const pcszKey, const int def/* = 0*/) const {213     int retValue                    =http://www.mamicode.com/ def;214     const char* pcszText            = this->readText(pcszSection, pcszKey, nullptr);215     if (nullptr != pcszText) {216         if (1 != sscanf(pcszText, "%d", &retValue)) {217             retValue                = http://www.mamicode.com/def; // 读取失败.218         }219     }220     return retValue;221 }222 223 unsigned int IniParser::readUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int def/* = 0u*/) const {224     unsigned int retValue           =http://www.mamicode.com/ def;225     const char* pcszText            = this->readText(pcszSection, pcszKey, nullptr);226     if (nullptr != pcszText) {227         if (1 != sscanf(pcszText, "%u", &retValue)) {228             retValue                = http://www.mamicode.com/def; // 读取失败.229         }230     }231     return retValue;232 }233 234 bool IniParser::readBool(const char* const pcszSection, const char* const pcszKey, const bool def/* = false*/) const {235     bool retValue                   =http://www.mamicode.com/ def;236     const char* pcszText            = this->readText(pcszSection, pcszKey, nullptr);237     if (nullptr != pcszText) {238         int iTempVal = 0;239         if (1 == sscanf(pcszText, "%d", &iTempVal)) {240             return 0 == iTempVal ? false : true;241         } else if (this->stringEqual(pcszText, "true")) {242             return true;243         } else {244             return false;245         }246     }247     return retValue;248 }249 250 float IniParser::readFloat(const char* const pcszSection, const char* const pcszKey, const float def/* = 0.0f*/) const {251     float retValue                  =http://www.mamicode.com/ def;252     const char* pcszText            = this->readText(pcszSection, pcszKey, nullptr);253     if (nullptr != pcszText) {254         if (1 != sscanf(pcszText, "%f", &retValue)) {255             retValue                = http://www.mamicode.com/def; // 读取失败.256         }257     }258     return retValue;259 }260 261 double IniParser::readDouble(const char* const pcszSection, const char* const pcszKey, const double def/* = 0.0*/) const {262     double retValue                 =http://www.mamicode.com/ def;263     const char* pcszText            = this->readText(pcszSection, pcszKey, nullptr);264     if (nullptr != pcszText) {265         if (1 != sscanf(pcszText, "%lf", &retValue)) {266             retValue                = http://www.mamicode.com/def; // 读取失败.267         }268     }269     return retValue;270 }271 272 const char* IniParser::readText(const char* const pcszSection, const char* const pcszKey, const char* const def/* = nullptr*/) const {273     const char* pcszRetValue        =http://www.mamicode.com/ def;274     auto pSection                   = this->getSection(pcszSection);275     if (nullptr != pSection) {276         pcszRetValue                = http://www.mamicode.com/pSection->read(pcszKey);277     }278     return pcszRetValue;279 }280 281 void IniParser::writeInt(const char* const pcszSection, const char* const pcszKey, const int value) {282     const size_t nBUFF_SIZE         = 256;283     char szBuff[nBUFF_SIZE];284     memset((void*)szBuff, 0x0L, nBUFF_SIZE);285     sprintf(szBuff, "%d", value);286     this->writeText(pcszSection, pcszKey, szBuff);287 }288 289 void IniParser::writeUnsignedInt(const char* const pcszSection, const char* const pcszKey, const unsigned int value) {290     const size_t nBUFF_SIZE         = 256;291     char szBuff[nBUFF_SIZE];292     memset((void*)szBuff, 0x0L, nBUFF_SIZE);293     sprintf(szBuff, "%u", value);294     this->writeText(pcszSection, pcszKey, szBuff);295 }296 297 void IniParser::writeBool(const char* const pcszSection, const char* const pcszKey, const bool value) {298     const size_t nBUFF_SIZE         = 256;299     char szBuff[nBUFF_SIZE];300     memset((void*)szBuff, 0x0L, nBUFF_SIZE);301     sprintf(szBuff, "%d", value ? 1 : 0);302     this->writeText(pcszSection, pcszKey, szBuff);303 }304 305 void IniParser::writeFloat(const char* const pcszSection, const char* const pcszKey, const float value) {306     const size_t nBUFF_SIZE         = 256;307     char szBuff[nBUFF_SIZE];308     memset((void*)szBuff, 0x0L, nBUFF_SIZE);309     sprintf(szBuff, "%g", value);310     this->writeText(pcszSection, pcszKey, szBuff);311 }312 313 void IniParser::writeDouble(const char* const pcszSection, const char* const pcszKey, const double value) {314     const size_t nBUFF_SIZE         = 256;315     char szBuff[nBUFF_SIZE];316     memset((void*)szBuff, 0x0L, nBUFF_SIZE);317     sprintf(szBuff, "%g", value);318     this->writeText(pcszSection, pcszKey, szBuff);319 }320 321 void IniParser::writeText(const char* const pcszSection, const char* const pcszKey, const char* const value) {322     if (nullptr != pcszSection && nullptr != pcszKey && nullptr != value) {323         auto iter                   = m_mapSectionName.find(pcszSection);324         Section* pSection           = nullptr;325         if (m_mapSectionName.end() == iter) {326             pSection                = new (std::nothrow) Section(pcszSection);327             if (nullptr == pSection) {328                 return;329             }330             m_listSections.emplace_back(pSection);331             m_mapSectionName[pcszSection] = --m_listSections.end();332         } else {333             pSection                = *(iter->second);334         }335         pSection->write(pcszKey, value);336     }337 }338 339 bool IniParser::remove(const char* const pcszSection, const char* const pcszKey) {340     auto bIsSuccess                 = false;341     if (nullptr != pcszSection) {342         auto iter                   = m_mapSectionName.find(pcszSection);343         if (m_mapSectionName.end() != iter) {344             auto pSection           = *(iter->second);345             if (nullptr != pSection) {346                 bIsSuccess          = pSection->remove(pcszKey);347             }348         }349     }350     return bIsSuccess;351 }352 353 bool IniParser::remove(const char* const pcszSection) {354     auto bIsSuccess                 = false;355     if (nullptr != pcszSection) {356         auto iter                   = m_mapSectionName.find(pcszSection);357         if (m_mapSectionName.end() != iter) {358             auto list_iter          = iter->second;359             Section* pSection       = *list_iter;360             if (nullptr != pSection) {361                 delete pSection;362                 pSection            = nullptr;363             }364             m_listSections.erase(list_iter);365             m_mapSectionName.erase(iter);366             bIsSuccess              = true;367         }368     }369     return bIsSuccess;370 }371 372 void IniParser::clear() {373     auto iter                       = m_listSections.begin();374     const auto iterend              = m_listSections.end();375     Section* pSection               = nullptr;376     for (; iterend != iter; ++iter) {377         pSection                    = *iter;378         if (nullptr != pSection) {379             delete pSection;380             pSection                = nullptr;381         }382     }383     m_listSections.clear();384     m_mapSectionName.clear();385 }386 387 Section* IniParser::getSection(const char* const pcszSection) const {388     Section* pRetSection            = nullptr;389     auto iter                       = m_mapSectionName.find(pcszSection);390     if (m_mapSectionName.end() != iter) {391         pRetSection                 = *(iter->second);392     }393     return pRetSection;394 }395 396 Section& IniParser::operator[](const char* const pcszSection) const {397     auto iter                       = m_mapSectionName.find(pcszSection);398     return *(*(iter->second));399 }400 401 void IniParser::trimLeft(char*& p, char*& q) {402     if (nullptr != p) {403         while (  == *p && ++p <= q);404     }405 }406 407 void IniParser::trimRight(char*& p, char*& q) {408     if (nullptr != q) {409         while (  == *q && --q >= p);410     }411 }412 413 void IniParser::trim(char*& p, char*& q) {414     this->trimLeft(p, q);415     this->trimRight(p, q);416 }417 418 void IniParser::trimRN0(char*& p, char*& q) {419     if (nullptr != q) {420         while ((\0 == *q || \r == *q || \n == *q) && --q >= p);421     }422 }423 424 bool IniParser::isEndWithN(const char* p, const size_t nLength) {425     if (0 == nLength) {426         return false;427     }428     const char* q = p + nLength;429     while (\0 == *q && --q >= p);430     return (q >= p) && (\n == *q);431 }432 433 bool IniParser::stringEqual(const char* p, const char* q, int nChar/* = INT_MAX*/) const {434     int n = 0;435     if (p == q) {436         return true;437     }438     while (*p && *q && *p == *q && n < nChar) {439         ++p;440         ++q;441         ++n;442     }443     if ((n == nChar) || (*p == 0 && *q == 0)) {444         return true;445     }446     return false;447 }448 449 bool IniParser::isSectionName(char* p, char* q) {450     if (nullptr == p || nullptr == q) {451         return false;452     }453     return [ == *p && ] == *q;454 }455 456 char* IniParser::splitKeyValue(char* p, char* q) {457     char* pRetEqualSignPos = p;458     while (= != *pRetEqualSignPos && ++pRetEqualSignPos < q);459     return pRetEqualSignPos;460 }461 462 void IniParser::parseIniLine(char* szIniLine) {463     char* p = szIniLine;464     char* q = p + strlen(p);465     this->trimRN0(p, q);466     this->trim(p, q);467     if (p < q) {468         // 只有这种情况才需要处理.因为 p > q,肯定不需要处理,说明全都是空格.如果p = q也不需要处理,因为只有一个字符还需要处理什么?469         *(q + 1) = \0;470         if (this->isSectionName(p, q)) {471             *q = \0;472             ++p;473             this->addSection(p);474         } else {475             char* szEqualSignPos = this->splitKeyValue(p, q);476             if (szEqualSignPos > p && szEqualSignPos < q) {477                 *szEqualSignPos = \0;478                 ++szEqualSignPos;479                 this->addParameter(p, szEqualSignPos);480             }481         }482     }483 }484 485 void IniParser::addSection(char* szSectionName) {486     auto iter                       = m_mapSectionName.find(szSectionName);487     if (m_mapSectionName.end() != iter) {488         // 已存在489         auto listiter               = iter->second;490         m_listSections.emplace_back(*listiter);491         m_listSections.erase(listiter);492         m_mapSectionName.erase(iter);493         m_mapSectionName[szSectionName] = --m_listSections.end();494         return;495     }496     Section* pSection               = new (std::nothrow) Section(szSectionName);497     if (nullptr == pSection) {498         return;499     }500     m_listSections.emplace_back(pSection);501     m_mapSectionName[szSectionName] = --m_listSections.end();502 }503 504 void IniParser::addParameter(char* szKey, char* szValue) {505     if (m_listSections.empty()) {506         return;507     }508     auto pSection                   = m_listSections.back();509     pSection->write(szKey, szValue);510 }511 512 }//namespace ns_ini
IniParser.cpp 文件

如果对该封装有改进或不当之处,欢迎指定、交流!

简单的INI解析封装