这篇文章简单讨论一下ini文件。
一.什么是ini文件
ini文件其实就是一种配置文件,常见于Windows的系统配置文件,当然也可以是其他用途,你的用法你说了算。
二.ini文件的格式一般是什么样的
看个例子
;这是注释
[section1]
key1=value1
key2=value2
[section2]
key3=value3
key4=value4
ini文件包括节(section)、键值对(通常称为参数,parameter)和注释(comment)。
1.节
1.每一个section包含若干个parameter。
2.每一个section独占一行,名称由[]包围,比如[sectionName]。
3.每一个section的生效范围,从当前section开始到下一个section的开始(或者文件结尾),这其中所有的parameter都属于这个section。
4.section不应该重复。
2.参数
1.parameter以键值对的形式存在,比如key=value。
2.同一个section中的parameter不应该重复。
3.注释
1.注释用;表示。
2.注释独占一行。
三.C++实现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;
}
四.其他
说一个小技巧,如果担心格式写的不对,可以用熟悉的编辑器中设置文档格式这个功能调整一下,当然调整之后也要进行确认。
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » C++解析ini文件
发表评论 取消回复