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獨占一行,名稱由[]包圍,比如[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.注釋獨占一行。
三.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)整之后也要進行確認(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-08
C++ 析構(gòu)函數(shù)與變量的生存周期實例詳解
這篇文章主要介紹了C++ 析構(gòu)函數(shù)與變量的生存周期實例詳解的相關(guān)資料2017-06-06
C++解決大數(shù)組棧內(nèi)存不夠問題的方法分析
這篇文章主要介紹了C++解決大數(shù)組棧內(nèi)存不夠問題的方法,結(jié)合實例形式對比分析了C++針對大數(shù)組棧內(nèi)存不足情況的常見解決方法及其優(yōu)缺點,具有一定參考借鑒價值,需要的朋友可以參考下2018-05-05

