网络上有很多C++编写的ini文件管理类,但功能全面的很少。我自己编写了一个ini文件的管理类,包括以下几个实用功能:
1、 ini文件读取功能
2、 ini文件键值修改功能
3、 支持各种注释,包括独立的多行注释、单行注释和键值行后注释。
下面是一个ini文件的例子:
;这是一个ini文件的例子
[root]
host=127.0.0.1
port=8989
// 温度
[temp]
name=温湿度
# 低温告警值
# 这里是举一个例子
low=30 # 最低温度
high = 40 ; 最高温度
[db]
type=mysql
databaseName=smg
具体的实现代码就是封装一个ini文件的类。
wsIni.h:
#include <string.h>
#ifndef SECTION_LEN
#define SECTION_LEN 30
#endif
#ifndef KEY_NAME_LEN
#define KEY_NAME_LEN 30
#endif
#ifndef KEY_VALUE_LEN
#define KEY_VALUE_LEN 100
#endif
#ifndef NOTE_LEN
#define NOTE_LEN 200
#endif
#ifndef SECTION_COMMENT_LEN
#define SECTION_COMMENT_LEN 1024
#endif
#ifndef ROW_COTENT_LEN
#define ROW_COTENT_LEN 1024
#endif
typedef struct KEY_VALUE
{
char szKeyName[KEY_NAME_LEN];
char szKeyValue[KEY_VALUE_LEN];
char szNote[NOTE_LEN]; // 和key同行的尾部备注
char *pszComment; // key行的前导注释,内容可能较多,因此动态分配空间
KEY_VALUE * pPre;
KEY_VALUE * pNext;
}T_KEY_VALUE;
typedef struct SECTION
{
char szSecName[SECTION_LEN];
char *pszComment; // 注释内容可能较多,因此动态分配空间
SECTION * pPre;
SECTION * pNext;
KEY_VALUE * pKeyValue;
}T_SECTION;
class wsIni
{
private:
public:
wsIni();
~wsIni();
int readIniFile(const char * pszFileName);
int writeIniFile(const char * pszFileName);
char * getKey(const char * pszSection, const char * pszKey);
int setKey(const char * pszSection, const char * pszKey, const char * pszValue, const char * pszComment, const char * pszNote);
void setSectionComment(const char * pszSection, const char * pszComment);
void printInfo();
private:
char * killBadChar(char * pszCon);
char * killValueComment(char *pszValue);
T_SECTION * m_pFirstSection;
T_SECTION * m_pCurSection;
T_KEY_VALUE * m_pCurKeyvalue;
};
在实现文件wsIni.cpp里,实现了头文件里的各个成员函数。其中最核心的就是读取ini文件的函数。
int wsIni::readIniFile(const char *pszFileName)
{
FILE *pFile = fopen(pszFileName, "r");
if (pFile == NULL)
{
printf("文件打开失败!");
return -1;
}
fseek(pFile, 0, SEEK_END); // 先将指针偏移到文件尾
long lLen = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
char *pszCon = new char[lLen + 2];
char *pszConSrc = pszCon;
memset(pszCon, 0, lLen + 2);
fread(pszCon, lLen, 1, pFile);
strcat(pszCon, "\n"); // 防止有的文件最后一行不是以换行符结尾
// printf(pszCon);
const char *s = "\n";
char *buf = strstr(pszCon, s);
char * pszCommentStart = pszCon;
char szLine[ROW_COTENT_LEN] = "";
while (buf != NULL)
{
int len = buf - pszCon;
memset(szLine, 0, ROW_COTENT_LEN);
strncpy(szLine, pszCon, len);
killBadChar(szLine);
if (strlen(szLine) > 0)
{
if (szLine[0] == '[') // section
{
// 该位置之前的认为是当前section的注释
int iComLen = pszCon - pszCommentStart;
char * pszCom = new char[iComLen + 1];
pszCom[iComLen] = '\0';
strncpy(pszCom, pszCommentStart, iComLen);
T_SECTION * pCurSection = new T_SECTION();
strncpy(pCurSection->szSecName, szLine + 1, strlen(szLine) - 2);
printf("section:%s\n", pCurSection->szSecName);
pCurSection->pNext = NULL;
pCurSection->pKeyValue = NULL;
pCurSection->pszComment = pszCom;
if (m_pFirstSection == NULL)
{
m_pFirstSection = pCurSection;
m_pFirstSection->pPre = NULL;
}
else
{
m_pCurSection->pNext = pCurSection;
pCurSection->pPre = m_pCurSection;
}
m_pCurSection = pCurSection;
pszCommentStart = buf + 1;
}
else if (szLine[0] == ';' || szLine[0] == '#' || (szLine[0] == '/' && szLine[1] == '/'))
{
printf("注释行\n");
}
else // key value
{
// 该位置之前的认为是当前key的注释
int iComLen = pszCon - pszCommentStart;
char * pszCom = new char[iComLen + 1];
pszCom[iComLen] = '\0';
strncpy(pszCom, pszCommentStart, iComLen);
T_KEY_VALUE *pKeyValue = new T_KEY_VALUE();
char *pszEqualFlag = strchr(szLine, '=');
strncpy(pKeyValue->szKeyName, szLine, pszEqualFlag - szLine);
char *pszValue = pszEqualFlag + 1;
pszValue = killBadChar(pszValue);
pszValue = killValueComment(pszValue);
strcpy(pKeyValue->szKeyValue, pszValue);
pKeyValue->pszComment = pszCom;
printf("key:%s value:%s\n", pKeyValue->szKeyName, pKeyValue->szKeyValue);
pKeyValue->pPre = NULL;
pKeyValue->pNext = NULL;
if (m_pCurSection->pKeyValue == NULL) // 当前section下的第一个节点
{
m_pCurSection->pKeyValue = pKeyValue;
}
else
{
m_pCurKeyvalue->pNext = pKeyValue;
pKeyValue->pPre = m_pCurKeyvalue;
}
m_pCurKeyvalue = pKeyValue;
pszCommentStart = buf + 1;
}
}
pszCon = buf + strlen(s);
buf = strstr(pszCon, s);
}
delete []pszConSrc;
fclose(pFile);
return 0;
}
测试代码:
#include <stdio.h>
#include "wsIni.h"
int main()
{
wsIni *obj = new wsIni();
obj->readIniFile("./a.ini");
obj->printInfo();
char *pszValue = obj->getKey("temp", "name");
printf("temp name:%s\n", pszValue);
obj->setKey("temp", "low", "33.3", "", ";最低温度");
obj->printInfo();
obj->writeIniFile("./b.ini");
delete obj;
return 0;
}
运行结果:
完整代码可以去这里下载:
http://kbase12.com/codedemo/doc/detail?id=c4046a4471cf41b7bdd63d049c1058bb