这篇文章简单讨论一下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#include #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; }
四.其他
说一个小技巧,如果担心格式写的不对,可以用熟悉的编辑器中设置文档格式这个功能调整一下,当然调整之后也要进行确认。