C++解析ini文件的實現(xiàn)方法
這篇文章簡單討論一下ini文件。
一.什么是ini文件
ini文件其實就是一種配置文件,常見于Windows的系統(tǒng)配置文件,當(dāng)然也可以是其他用途,你的用法你說了算。
二.ini文件的格式一般是什么樣的
看個例子
;這是注釋 [section1] key1=value1 key2=value2 [section2] key3=value3 key4=value4
ini文件包括節(jié)(section)、鍵值對(通常稱為參數(shù),parameter)和注釋(comment)。
1.節(jié)
1.每一個section包含若干個parameter。
2.每一個section獨(dú)占一行,名稱由[]包圍,比如[sectionName]。
3.每一個section的生效范圍,從當(dāng)前section開始到下一個section的開始(或者文件結(jié)尾),這其中所有的parameter都屬于這個section。
4.section不應(yīng)該重復(fù)。
2.參數(shù)
1.parameter以鍵值對的形式存在,比如key=value。
2.同一個section中的parameter不應(yīng)該重復(fù)。
3.注釋
1.注釋用;表示。
2.注釋獨(dú)占一行。
三.C++實現(xiàn)ini文件的解析
重點來了,這里展示一種C++解析ini文件的簡易代碼寫法,主要是描述一種解析的思維,大致測試過了。
直接看代碼
//inifile.h #ifndef INIFILE_H #define INIFILE_H #include <iostream> #include <string> #define ERR_MES_1 "輸入值不合法" #define ERR_MES_2 "打開文件失敗" #define ERR_MES_3 "配置項不存在" const char TYPE_NULL = '0'; const char TYPE_SECTION = '1'; const char TYPE_PARAMETER = '2'; const char TYPE_COMMENT = '3'; typedef struct IniNode { char m_Type; std::string m_Text; IniNode* m_pPrev; IniNode* m_pNext; }IniNode, * pIniNode; typedef struct IniSec { pIniNode m_pSection; pIniNode m_pParameter; std::string m_SectionText; std::string m_ParameterText; }IniSec, * pIniSec; class IniFile { public: IniFile(); ~IniFile(); bool ReadIniFile(const char* FilePathName); bool WriteIniFile(const char* FilePathName); bool WriteParameter(const char* Section, const char* Key, const char* Value); bool WriteParameter(const char* Section, const char* Key, const bool Value); bool WriteParameter(const char* Section, const char* Key, const int Value); bool WriteParameter(const char* Section, const char* Key, const double Value); std::string ReadParameter(const char* Section, const char* Key, const char* Default); bool ReadParameter(const char* Section, const char* Key, const bool Default); int ReadParameter(const char* Section, const char* Key, const int Default); double ReadParameter(const char* Section, const char* Key, const double Default); bool DeleteParameter(const char* Section, const char* Key); bool DeleteSection(const char* Section); int GetErrCode(); std::string GetErrMes(); protected: void FreeIniList(); void CreateIniNode(); void Trim(char* Buffer); pIniNode FindSection(const char* Section); pIniSec FindParameter(const char* Section, const char* Key); void AddIniNode(char Type, const char* Text); bool WriteParameterPublic(const char* Section, const char* Key, const char* Value); std::string ReadParameterPublic(const char* Section, const char* Key, const char* Default); private: FILE* m_pIniFileHandle; pIniNode m_pIniList; pIniNode m_pCurIniNode; int m_LastErrCode; std::string m_LastErrMes; }; #endif // !INIFILE_H
//inifile.cpp #include "inifile.h" IniFile::IniFile() { m_LastErrCode = 0; m_LastErrMes = ""; m_pCurIniNode = nullptr; m_pIniFileHandle = nullptr; m_pIniList = nullptr; } IniFile::~IniFile() { FreeIniList(); fclose(m_pIniFileHandle); } int IniFile::GetErrCode() { return m_LastErrCode; } std::string IniFile::GetErrMes() { return m_LastErrMes; } bool IniFile::ReadIniFile(const char* FilePathName) { if (!strcmp(FilePathName, "")) { m_LastErrCode = 1; m_LastErrMes = ERR_MES_1; return false; } if (!(m_pIniFileHandle = fopen(FilePathName, "r"))) { m_LastErrCode = 2; m_LastErrMes = ERR_MES_2; return false; } FreeIniList(); char filebuf[256] = { 0 }; char* pchr = nullptr; while (fgets(filebuf, 256, m_pIniFileHandle)) { Trim(filebuf); CreateIniNode(); if (';' == filebuf[0]) { m_pCurIniNode->m_Type = TYPE_COMMENT; } else if ('[' == filebuf[0] && strchr(filebuf, ']')) { m_pCurIniNode->m_Type = TYPE_SECTION; } else if (strchr(filebuf, '=')) { m_pCurIniNode->m_Type = TYPE_PARAMETER; } else { m_pCurIniNode->m_Type = TYPE_NULL; } m_pCurIniNode->m_Text = filebuf; } fclose(m_pIniFileHandle); return true; } bool IniFile::WriteIniFile(const char* FilePathName) { if (!strcmp(FilePathName, "")) { m_LastErrCode = 1; m_LastErrMes = ERR_MES_1; return false; } char FilePathNameBat[256] = { 0 }; strcpy(FilePathNameBat, FilePathName); strcat(FilePathNameBat, ".bak"); FILE* FileIniTemp = fopen(FilePathName, "r"); FILE* FileBatTemp = fopen(FilePathNameBat, "w"); if (!FileIniTemp || !FileBatTemp) { m_LastErrCode = 2; m_LastErrMes = ERR_MES_2; return false; } char FileStr[256] = { 0 }; while (fgets(FileStr, 256, FileIniTemp)) { fprintf(FileBatTemp, "%s", FileStr); } fclose(FileIniTemp); fclose(FileBatTemp); if (!(m_pIniFileHandle = fopen(FilePathName, "w"))) { m_LastErrCode = 2; m_LastErrMes = ERR_MES_2; return false; } m_pCurIniNode = m_pIniList; while (m_pCurIniNode) { fprintf(m_pIniFileHandle, "%s\n", m_pCurIniNode->m_Text.data()); m_pCurIniNode = m_pCurIniNode->m_pNext; } fclose(m_pIniFileHandle); return true; } bool IniFile::WriteParameter(const char* Section, const char* Key, const char* Value) { return WriteParameterPublic(Section, Key, Value); } bool IniFile::WriteParameter(const char* Section, const char* Key, const bool Value) { char StrValue[256] = { 0 }; itoa(Value, StrValue, 2); return WriteParameterPublic(Section, Key, StrValue); } bool IniFile::WriteParameter(const char* Section, const char* Key, const int Value) { char StrValue[256] = { 0 }; itoa(Value, StrValue, 10); return WriteParameterPublic(Section, Key, StrValue); } bool IniFile::WriteParameter(const char* Section, const char* Key, const double Value) { char StrValue[256] = { 0 }; sprintf_s(StrValue, "%f", Value); return WriteParameterPublic(Section, Key, StrValue); } std::string IniFile::ReadParameter(const char* Section, const char* Key, const char* Default) { return ReadParameterPublic(Section, Key, Default); } bool IniFile::ReadParameter(const char* Section, const char* Key, const bool Default) { char DefaultString[2] = { 0 }; if (Default) { DefaultString[0] = '1'; } else { DefaultString[0] = '0'; } std::string RetStr = ReadParameterPublic(Section, Key, DefaultString); return atoi(RetStr.data()); } int IniFile::ReadParameter(const char* Section, const char* Key, const int Default) { char DefaultString[256] = { 0 }; itoa(Default, DefaultString, 10); std::string RetStr = ReadParameterPublic(Section, Key, DefaultString); return atoi(RetStr.data()); } double IniFile::ReadParameter(const char* Section, const char* Key, const double Default) { char DefaultString[256] = { 0 }; sprintf_s(DefaultString, "%f", Default); std::string RetStr = ReadParameterPublic(Section, Key, DefaultString); return atof(RetStr.data()); } bool IniFile::DeleteParameter(const char* Section, const char* Key) { if (!strcmp(Section, "") || !strcmp(Key, "")) { m_LastErrCode = 1; m_LastErrMes = ERR_MES_1; return false; } pIniSec pIniSecTemp = FindParameter(Section, Key); if (!pIniSecTemp) { m_LastErrCode = 3; m_LastErrMes = ERR_MES_3; return false; } m_pCurIniNode = pIniSecTemp->m_pParameter; m_pCurIniNode->m_pPrev->m_pNext = m_pCurIniNode->m_pNext; if (m_pCurIniNode->m_pNext) { m_pCurIniNode->m_pNext->m_pPrev = m_pCurIniNode->m_pPrev; } delete m_pCurIniNode; delete pIniSecTemp; return true; } bool IniFile::DeleteSection(const char* Section) { if (!strcmp(Section, "")) { m_LastErrCode = 1; m_LastErrMes = ERR_MES_1; return false; } pIniNode pSectionIniNodeTemp = FindSection(Section); if (!pSectionIniNodeTemp) { m_LastErrCode = 3; m_LastErrMes = ERR_MES_3; return false; } pIniNode pCurNextIniNode = nullptr; m_pCurIniNode = pSectionIniNodeTemp->m_pNext; while (m_pCurIniNode && m_pCurIniNode->m_Type == TYPE_PARAMETER) { pCurNextIniNode = m_pCurIniNode->m_pNext; m_pCurIniNode->m_pPrev->m_pNext = m_pCurIniNode->m_pNext; if (m_pCurIniNode->m_pNext) { m_pCurIniNode->m_pNext->m_pPrev = m_pCurIniNode->m_pPrev; } delete m_pCurIniNode; m_pCurIniNode = pCurNextIniNode; } m_pCurIniNode = pSectionIniNodeTemp; m_pCurIniNode->m_pPrev->m_pNext = m_pCurIniNode->m_pNext; if (m_pCurIniNode->m_pNext) { m_pCurIniNode->m_pNext->m_pPrev = m_pCurIniNode->m_pPrev; } delete m_pCurIniNode; return true; } void IniFile::FreeIniList() { if (nullptr == m_pIniList) { return; } pIniNode pNextIniNodeTemp = nullptr; while (nullptr != m_pIniList) { pNextIniNodeTemp = m_pIniList->m_pNext; delete m_pIniList; m_pIniList = pNextIniNodeTemp; } } void IniFile::CreateIniNode() { pIniNode pIniNodeTemp = new IniNode; memset(pIniNodeTemp, 0, sizeof(IniNode)); if (nullptr == m_pIniList) { m_pIniList = pIniNodeTemp; m_pCurIniNode = pIniNodeTemp; return; } m_pCurIniNode = m_pIniList; while (m_pCurIniNode->m_pNext) { m_pCurIniNode = m_pCurIniNode->m_pNext; } m_pCurIniNode->m_pNext = pIniNodeTemp; pIniNodeTemp->m_pPrev = m_pCurIniNode; m_pCurIniNode = pIniNodeTemp; } void IniFile::Trim(char* Buffer) { int i = 0; int len = strlen(Buffer); for (i = len - 1; i >= 0; i--) { if (' ' != Buffer[i] && '\t' != Buffer[i] && '\n' != Buffer[i]) { break; } Buffer[i] = 0; } for (i = 0; i < len; i++) { if (' ' != Buffer[i] && '\t' != Buffer[i] && '\n' != Buffer[i]) { break; } } if (0 != i) { strncpy(Buffer, Buffer + i, len - i); Buffer[len - i] = 0; } } pIniNode IniFile::FindSection(const char* Section) { m_pCurIniNode = m_pIniList; while (m_pCurIniNode) { if (!strcmp(m_pCurIniNode->m_Text.data(), Section) && m_pCurIniNode->m_Type == TYPE_SECTION) { return m_pCurIniNode; } m_pCurIniNode = m_pCurIniNode->m_pNext; } return nullptr; } pIniSec IniFile::FindParameter(const char* Section, const char* Key) { m_pCurIniNode = m_pIniList; pIniSec pIniSecTemp = new IniSec; char Buf[256] = { 0 }; char* pChr = nullptr; while (m_pCurIniNode) { if (!strcmp(m_pCurIniNode->m_Text.data(), Section) && m_pCurIniNode->m_Type == TYPE_SECTION) { pIniSecTemp->m_pSection = m_pCurIniNode; pIniSecTemp->m_SectionText = m_pCurIniNode->m_Text; m_pCurIniNode = m_pCurIniNode->m_pNext; while (m_pCurIniNode && m_pCurIniNode->m_Type == TYPE_PARAMETER) { strcpy(Buf, m_pCurIniNode->m_Text.data()); if (pChr = strchr(Buf, '=')) { *pChr = 0; Trim(Buf); if (!strcmp(Buf, Key)) { pIniSecTemp->m_pParameter = m_pCurIniNode; pIniSecTemp->m_ParameterText = m_pCurIniNode->m_Text; return pIniSecTemp; } } m_pCurIniNode = m_pCurIniNode->m_pNext; } break; } m_pCurIniNode = m_pCurIniNode->m_pNext; } delete pIniSecTemp; return nullptr; } void IniFile::AddIniNode(char Type, const char* Text) { if (Type == TYPE_SECTION) { m_pCurIniNode->m_Type = TYPE_SECTION; m_pCurIniNode->m_Text = Text; } else if (Type == TYPE_PARAMETER) { m_pCurIniNode->m_Type = TYPE_PARAMETER; m_pCurIniNode->m_Text = Text; } return; } bool IniFile::WriteParameterPublic(const char* Section, const char* Key, const char* Value) { if (!strcmp(Section, "") || !strcmp(Key, "") || !strcmp(Value, "")) { m_LastErrCode = 1; m_LastErrMes = ERR_MES_1; return false; } char Parameter[256] = { 0 }; strcpy(Parameter, Key); strcat(Parameter, "="); strcat(Parameter, Value); pIniNode pSectionNodeTemp = FindSection(Section); pIniSec pIniSecTemp = nullptr; if (!pSectionNodeTemp) { CreateIniNode(); AddIniNode(TYPE_SECTION, Section); CreateIniNode(); AddIniNode(TYPE_PARAMETER, Parameter); } else { if (!(pIniSecTemp = FindParameter(Section, Key))) { pIniNode pIniNodeTemp = new IniNode; memset(pIniNodeTemp, 0, sizeof(IniNode)); pIniNodeTemp->m_pNext = pSectionNodeTemp->m_pNext; pSectionNodeTemp->m_pNext = pIniNodeTemp; if (pIniNodeTemp->m_pNext) { pIniNodeTemp->m_pNext->m_pPrev = pIniNodeTemp; } pIniNodeTemp->m_pPrev = pSectionNodeTemp; m_pCurIniNode = pIniNodeTemp; AddIniNode(TYPE_PARAMETER, Parameter); } else { m_pCurIniNode = pIniSecTemp->m_pParameter; AddIniNode(TYPE_PARAMETER, Parameter); } } delete pIniSecTemp; pIniSecTemp = nullptr; return true; } std::string IniFile::ReadParameterPublic(const char* Section, const char* Key, const char* Default) { if (!strcmp(Section, "") || !strcmp(Key, "") || !strcmp(Default, "")) { m_LastErrCode = 1; m_LastErrMes = ERR_MES_1; return {}; } std::string Ret; pIniSec pIniSecTemp = FindParameter(Section, Key); char* pChr = nullptr; if (pIniSecTemp) { char Buf[256] = { 0 }; strcpy(Buf, pIniSecTemp->m_ParameterText.data()); if (pChr = strchr(Buf, '=')) { strcpy(Buf, pChr + 1); } Ret = Buf; } else { Ret = Default; } delete pIniSecTemp; return Ret; }
四.其他
說一個小技巧,如果擔(dān)心格式寫的不對,可以用熟悉的編輯器中設(shè)置文檔格式這個功能調(diào)整一下,當(dāng)然調(diào)整之后也要進(jìn)行確認(rèn)。
到此這篇關(guān)于C++解析ini文件實現(xiàn)的文章就介紹到這了,更多相關(guān)C++解析ini文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言編程中分配內(nèi)存空間的相關(guān)函數(shù)
這篇文章主要介紹了C語言編程中分配內(nèi)存空間的相關(guān)函數(shù),分別是malloc()函數(shù)和calloc()函數(shù),需要的朋友可以參考下2015-08-08C++ 析構(gòu)函數(shù)與變量的生存周期實例詳解
這篇文章主要介紹了C++ 析構(gòu)函數(shù)與變量的生存周期實例詳解的相關(guān)資料2017-06-06C++解決大數(shù)組棧內(nèi)存不夠問題的方法分析
這篇文章主要介紹了C++解決大數(shù)組棧內(nèi)存不夠問題的方法,結(jié)合實例形式對比分析了C++針對大數(shù)組棧內(nèi)存不足情況的常見解決方法及其優(yōu)缺點,具有一定參考借鑒價值,需要的朋友可以參考下2018-05-05