背景:编程过程中经常会遇到读取Ini文件的场合,封装一个方便的类,能否避免重复编写,以后可复用。ini文件的格式很简单,并且不像xml之类的配置文件严谨。通常用于配置简单的键值对。
本类测试文件如下:<server.ini>
#what
[server1]
ip= 192.168.1.1
port=8888
type=ai
#no
[server2]
ip=10.10.10.10
port=5002
type=move
#shit
[server3]
ip=127.0.0.1
port=9527
type=cache
/*********************头文件 inifile.h *********************************/
#ifndef _INI_FILE_ #define _INI_FILE_ #include <string> #include <map> #include <iostream> using namespace std; #define MAX_LINE_BUF_SIZE 80 #define MAX_SECTION_CONTEXT_BUF_SIZE 40 #define MAX_KEY_SIZE 40 #define MAX_VALUE_SIZE 40 class IniFile { typedef std::map< string, string > MapKeyValue; typedef map< string, MapKeyValue > MapSection; public: IniFile(); ~IniFile(); bool Init(char* szFileName); void Save(); bool SaveAs(char* szFileName); void ShowFileContext(); string GetValue(const string& strKey); string GetValueFromSection(const string& strSection, const string& strKey); int GetInt(const string& strKey); float GetFloat(const string& strKey); private: void DelInvalidSign(char* szOldLine, char* szNewLine); bool IsNoteLine(char* szLine); bool IsEmptyLine(char* szLine); bool IsNewSection(char* szLine); bool IsKeyValueLine(char* szLine); bool GetNewSectionContext(char* szLine, string& strNewSectionContext); bool GetKeyValue(char* szLine, string& strKey, string& strValue); private: string m_strFileName; MapSection m_mapSection; }; #endif
/***************实现文件 inifile.cpp******************/
#include "inifile.h" IniFile::IniFile( ) { } IniFile::~IniFile() { } bool IniFile::Init( char* szFileName ) { if (NULL == szFileName || strlen(szFileName) == 0) { return false; } m_strFileName = szFileName; FILE* pFile = fopen( szFileName, "rb" ); if (NULL == pFile) { return false; } char szReadLineBuf[MAX_LINE_BUF_SIZE]; char szLineBuf[MAX_LINE_BUF_SIZE]; string strCurSection; string strKey; string strValue; while(NULL != fgets(szReadLineBuf, MAX_LINE_BUF_SIZE, pFile)) { DelInvalidSign(szReadLineBuf, szLineBuf); if (IsNoteLine(szLineBuf) || IsEmptyLine(szLineBuf)) { continue; } else if (IsNewSection(szLineBuf)) { GetNewSectionContext(szLineBuf, strCurSection); } else if (IsKeyValueLine(szLineBuf)) { GetKeyValue(szLineBuf, strKey, strValue); m_mapSection[strCurSection][strKey] = strValue; } else { continue; } } return true; } bool IniFile::IsNoteLine( char* szLine ) { return (szLine[0] == '#'); } bool IniFile::IsEmptyLine( char* szLine ) { int nLineSize = strlen(szLine); if (nLineSize == 0) { return true; } else { return false; } } bool IniFile::IsNewSection( char* szLine ) { return (strchr(szLine, '[') && strchr(szLine, ']')); } bool IniFile::IsKeyValueLine( char* szLine ) { return (NULL != strchr(szLine, '=')); } bool IniFile::GetNewSectionContext( char* szLine, string& strNewSectionContext ) { char szSectionContextBuf[MAX_SECTION_CONTEXT_BUF_SIZE] = {0}; strNewSectionContext.clear(); char* pSectionContextBegin = strchr(szLine, '['); char* pSectionContextEnd = strchr(szLine, ']'); int nSectionContextLen = pSectionContextEnd - pSectionContextBegin - 1; memcpy_s(szSectionContextBuf, MAX_SECTION_CONTEXT_BUF_SIZE, pSectionContextBegin + 1, nSectionContextLen); strNewSectionContext = szSectionContextBuf; return true; } bool IniFile::GetKeyValue( char* szLine, string& strKey, string& strValue ) { strKey.clear(); strValue.clear(); char* pEqualPos = strchr(szLine, '='); char szKeyBuf[MAX_KEY_SIZE] = {0}; char szValueBuf[MAX_VALUE_SIZE] = {0}; int nKeyLen = pEqualPos - szLine; int nValueLen = strlen(szLine) - nKeyLen - 1; memcpy_s(szKeyBuf, MAX_KEY_SIZE, szLine, nKeyLen); strKey = szKeyBuf; memcpy_s(szValueBuf, MAX_VALUE_SIZE, pEqualPos + 1, nValueLen); strValue = szValueBuf; return true; } void IniFile::Save() { } bool IniFile::SaveAs( char* szFileName ) { if (NULL == szFileName || strlen(szFileName) == 0) { return false; } FILE* pFile = fopen(szFileName, "w"); if (NULL == pFile) { return false; } // 写入文件内容 MapSection::iterator itSection = m_mapSection.begin(); for (; itSection != m_mapSection.end(); itSection++) { MapKeyValue& refKeyValueMap = itSection->second; fprintf(pFile, "[%s]\n", itSection->first.c_str()); MapKeyValue::iterator itKV = refKeyValueMap.begin(); for (; itKV != refKeyValueMap.end(); itKV++) { fprintf(pFile, "%s=%s\n", itKV->first.c_str(), itKV->second.c_str()); } fprintf(pFile, "\n"); } return true; } void IniFile::ShowFileContext() { MapSection::iterator itSection = m_mapSection.begin(); for (; itSection != m_mapSection.end(); itSection++) { MapKeyValue& refKeyValueMap = itSection->second; cout << "==============================" << endl; cout << "Section:" << itSection->first << endl; MapKeyValue::iterator itKV = refKeyValueMap.begin(); for (; itKV != refKeyValueMap.end(); itKV++) { cout << itKV->first << " = " << itKV->second << endl; } cout << "==============================" << endl; cout << endl; } } void IniFile::DelInvalidSign( char* szOldLine, char* szNewLine ) { int iOldLineLen; if (NULL == szOldLine || (iOldLineLen = strlen(szOldLine)) == 0) { return; } char tmpChar; int nNewLineIndex = 0; for (int i = 0; i < iOldLineLen; i++) { tmpChar = szOldLine[i]; if (tmpChar == ' ' || tmpChar == '\t' || tmpChar == '\r' || tmpChar == '\n') { continue; } szNewLine[nNewLineIndex++] = tmpChar; } szNewLine[nNewLineIndex] = 0; } std::string IniFile::GetValue( const string& strKey ) { MapSection::iterator itSection = m_mapSection.begin(); for (; itSection != m_mapSection.end(); itSection++) { MapKeyValue& refKeyValueMap = itSection->second; MapKeyValue::iterator itKV = refKeyValueMap.find(strKey); if (itKV != refKeyValueMap.end()) { return itKV->second; } } return ""; } std::string IniFile::GetValueFromSection( const string& strSection, const string& strKey ) { MapSection::iterator itSection = m_mapSection.find(strSection); if (itSection == m_mapSection.end()) { return ""; } MapKeyValue& refKeyValueMap = itSection->second; MapKeyValue::iterator itKV = refKeyValueMap.find(strKey); if (itKV != refKeyValueMap.end()) { return itKV->second; } return ""; } int IniFile::GetInt( const string& strKey ) { string str = GetValue(strKey); return atoi(str.c_str()); } float IniFile::GetFloat( const string& strKey ) { string str = GetValue(strKey); return atof(str.c_str()); } //因为配置文件中记录的数据均以字符串形式独处,可以根据需要获取的数据类型,自行定义Get***类型的函数集
// 测试用代码#include "inifile.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { IniFile file; if (!file.Init("server.ini")) { return -1; } // 现实配置文件的全部内容 file.ShowFileContext(); cout << file.GetInt("port") << endl; cout << file.GetValueFromSection("server2","ip") << endl; // 将文件另存为 //file.SaveAs("heihei.ini"); return 0; }