INI文件解析、遍历

来源:互联网 发布:js array删除方法 编辑:程序博客网 时间:2024/05/21 21:39

工作中时常需要给软件添加配置文件功能,INI文件简单又高效,但是微软的那套API使用太不方便,尤其是INI文件的遍历,所有花了一下午时间造了个轮子,自己解析INI文件。

目前只能读取Unicode小端编码,就是用windows记事本另存为时编码选择Unicode。
这里写图片描述

INI文件中元素分为节名、键和值,比如
[section]
key=value

键值必须属于某个节,节名必须放在中括号内,键和值中用等号隔开,一行只能有一对键值和一个节(就是必须分行)。本轮子内的键名可以有多个 ‘[’ 但不能有 ‘]’和 ‘=’,键中可以有 ‘[’ 但不能有 ‘]’和 ‘=’(’=’会被截断),值中可以有任何字符。空格和注释会被忽略,注释是以 ‘;’ 开头的行 。

下面是代码:

Ini.h

#pragma once#include <afxwin.h>#include <iostream>#include <map>#include <vector>class CIni{public:    // Ini文件中的键值对表    typedef std::map<std::wstring, std::wstring> KValueTable;       // Ini文件中的节    typedef struct Section    {        std::wstring sectionName;        KValueTable kValueTable;    }*PSection;    // Ini文件中的节表    typedef std::vector<Section> SectionTable;    CIni();    ~CIni();    // 加载Ini文件,返回值  -2:文件读取错误; -1:不支持的编码; 0:正确; > 0:解析错误的行数(第几号)    int Load(TCHAR *fileName);    // 保存Ini文件    bool Save(TCHAR *fileName);    // 清空节表    void Clear() { m_sectionTable.clear(); }    // 添加节    bool AddSection(TCHAR *sectionName);    // 添加键值    bool AddKValue(TCHAR *sectionName, TCHAR *key, TCHAR *value);    // 通过节名和键名获取值    const TCHAR *GetValue(TCHAR *sectionName, TCHAR *key);    // 通过节名和键名修改值    bool UpdateValue(TCHAR *sectionName, TCHAR *key, TCHAR *value);    // 获取节表    const SectionTable &GetSectionTable() const { return m_sectionTable; }    // 解析正常返回 0,不能处理的编码返回-1, 否则返回失败的行数(目前只能解析小端unicode编码)    int Parse(TCHAR *text, int size, SectionTable &sectionTable);    // ini文件内容(树形式)    std::wstring ToString();private:    SectionTable m_sectionTable;        // 节表};

Ini.cpp

#include "Ini.h"#include <fstream>CIni::CIni(){}CIni::~CIni(){}int CIni::Load(TCHAR * fileName){    // 清空节表    m_sectionTable.clear();    // 打开文件    CFile file;    if (!file.Open(fileName, CFile::modeRead)) { return -1; }    // 获取文件大小    CFileStatus fileStatus;    file.GetStatus(fileStatus);    int fileSize = fileStatus.m_size;    // 读取文件    TCHAR *text = new TCHAR[fileSize / 2 + 10];    int readLength = file.Read(text, fileSize);    if (readLength != fileSize)     {         file.Close();        return -1;    }    // 解析文件    int errorRow = Parse(text, fileSize / 2, m_sectionTable);    delete[] text;    file.Close();    return errorRow;}bool CIni::Save(TCHAR * fileName){    CFile file;    if (!file.Open(fileName, CFile::modeCreate | CFile::modeWrite)) { return false; }    const TCHAR left = _T('[');                         // 节名左中括号    const TCHAR right = _T(']');                        // 节名右中括号    const TCHAR equal = _T('=');                        // 等号    const TCHAR newLine[2] = {_T('\r'), _T('\n')};      // 回车换行    // 遍历节表    for (auto it = m_sectionTable.begin(); it != m_sectionTable.end(); ++it)    {        file.Write(&left, 2);        file.Write(it->sectionName.c_str(), it->sectionName.length() * 2);        file.Write(&right, 2);        file.Write(newLine, 4);        // 遍历键值表        for (auto i = it->kValueTable.begin(); i != it->kValueTable.end(); ++i)        {            file.Write(i->first.c_str(), i->first.length() * 2);            file.Write(&equal, 2);            file.Write(i->second.c_str(), i->second.length() * 2);            file.Write(newLine, 4);        }    }    return true;}bool CIni::AddSection(TCHAR *sectionName){    std::wstring wSectionName(sectionName);    for (auto it = m_sectionTable.begin(); it != m_sectionTable.end(); ++it)    {        if (it->sectionName == wSectionName)        {            return false;        }    }    Section section;    section.sectionName = wSectionName;    m_sectionTable.push_back(section);    return true;}bool CIni::AddKValue(TCHAR *sectionName, TCHAR *key, TCHAR *value){    std::wstring wSectionName(sectionName);    std::wstring wKey(key);    std::wstring wValue(value);    for (auto it = m_sectionTable.begin(); it != m_sectionTable.end(); ++it)    {        if (it->sectionName == wSectionName)        {            it->kValueTable[wKey] = wValue;            return true;        }    }    return false;}const TCHAR *CIni::GetValue(TCHAR * sectionName, TCHAR * key){    std::wstring wSectionName(sectionName);    std::wstring wKey(key);    for (auto it = m_sectionTable.begin(); it != m_sectionTable.end(); ++it)    {        if (it->sectionName == wSectionName)        {            auto temp = it->kValueTable.find(wKey);            if (temp == it->kValueTable.end())            {                return nullptr;            }            else            {                return temp->second.c_str();            }        }    }    return nullptr;}bool CIni::UpdateValue(TCHAR * sectionName, TCHAR * key, TCHAR * value){    std::wstring wSectionName(sectionName);    std::wstring wKey(key);    std::wstring wValue(value);    for (auto it = m_sectionTable.begin(); it != m_sectionTable.end(); ++it)    {        if (it->sectionName == wSectionName)        {            auto temp = it->kValueTable.find(wKey);            if (temp == it->kValueTable.end())            {                return false;            }            else            {                temp->second = wValue;                return true;            }        }    }    return false;}int CIni::Parse(TCHAR * text, int size, SectionTable & sectionTable){    TCHAR sectionName[100] = {0};       // 节名    int sectionIndex = 0;               // 节名下标    TCHAR key[100] = { 0 };             // 键    int keyIndex = 0;                   // 键下标    TCHAR value[2000] = {0};            // 值    int valueIndex = 0;                 // 值下标    bool isSection = false;             // 当前字符是节名    bool isKey = false;                 // 当前字符是键    bool isValue = false;               // 当前字符是值    bool isComment = false;             // 当前字符是注释    // 失败行数    int errorRow = 0;    // 小端    if (*text == 0xFEFF)    {        ++text;        --size;    }    // 大端不能解析    if (*text == 0xFFFE)    {        return -1;    }    for (int i = 0; i < size; ++i)    {        if (text[i] == _T('['))        {            if (!isComment)            {                if (isKey)                {                    key[keyIndex] = text[i];                    ++keyIndex;                }                else if (isValue)                {                    value[valueIndex] = text[i];                    ++valueIndex;                }                else if (isSection)                {                    ++errorRow;                    return errorRow;                }                else                {                    TCHAR *pTemp = text + i + 1;                    while (!(*pTemp == _T('\r') && *(pTemp + 1) == _T('\n')) && *pTemp != 0)                    {                        if (*pTemp == _T('='))                        {                            isKey = true;                            memset(key, sizeof(key), 0);                            key[0] = text[i];                            keyIndex = 1;                            break;                        }                        else if (*pTemp == _T(']'))                        {                            TCHAR *pTemp2 = pTemp + 1;                            while (!(*pTemp2 == _T('\r') && *(pTemp2 + 1) == _T('\n')) && *pTemp2 != 0)                            {                                if (*pTemp2 != _T(' '))                                {                                    break;                                }                                ++pTemp2;                            }                            if (*pTemp2 == 0)                            {                                ++errorRow;                                return errorRow;                            }                            if ((*pTemp2 == _T('\r') && *(pTemp2 + 1) == _T('\n')))                            {                                isSection = true;                                memset(sectionName, sizeof(sectionName), 0);                                sectionIndex = 0;                                break;                            }                        }                        ++pTemp;                    }                    if ((*pTemp == _T('\r') && *(pTemp + 1) == _T('\n')) || *pTemp == 0)                    {                        ++errorRow;                        return errorRow;                    }                }            }        }        else if (text[i] == _T(']'))        {            if (!isComment)            {                if (isSection)                {                    sectionName[sectionIndex] = 0;                    Section section;                    section.sectionName = sectionName;                    sectionTable.push_back(section);                    isSection = false;                    memset(sectionName, sizeof(sectionName), 0);                    sectionIndex = 0;                    TCHAR *pTemp = text + i + 1;                    while (!(*pTemp == _T('\r') && *(pTemp + 1) == _T('\n')) && *pTemp != 0)                    {                        if (*pTemp != _T(' '))                        {                            break;                        }                        ++pTemp;                    }                    if (!(*pTemp == _T('\r') && *(pTemp + 1) == _T('\n')) && *pTemp != 0)                    {                        ++errorRow;                        return errorRow;                    }                }                else if (isKey)                {                    key[keyIndex] = text[i];                    ++keyIndex;                }                else if (isValue)                {                    value[valueIndex] = text[i];                    ++valueIndex;                }                else                {                    ++errorRow;                    return errorRow;                }            }        }        else if (text[i] == _T('='))        {            if (!isComment)            {                if (isKey)                {                    key[keyIndex] = 0;                    isKey = false;                    if (isValue)                    {                        ++errorRow;                        return errorRow;                    }                    isValue = true;                }                else if (isSection)                {                    sectionName[sectionIndex] = text[i];                    ++sectionIndex;                }                else if (isValue)                {                    value[valueIndex] = text[i];                    ++valueIndex;                }                else                {                    ++errorRow;                    return errorRow;                }            }        }        else if ((text[i] == _T('\r') && text[i + 1] == _T('\n')))        {            isComment = false;            if (isValue)            {                if (isSection || isKey)                {                    ++errorRow;                    return errorRow;                }                value[valueIndex] = 0;                std::wstring wKey(key);                std::wstring wValue(value);                if (sectionTable.size() <= 0)                 {                    ++errorRow;                    return errorRow;                }                sectionTable[sectionTable.size() - 1].kValueTable[wKey] = wValue;                memset(key, sizeof(key), 0);                keyIndex = 0;                isValue = false;                memset(value, sizeof(value), 0);                valueIndex = 0;            }            else if (isKey || isSection)            {                ++errorRow;                return errorRow;            }            ++errorRow;            ++i;        }        else if (text[i] == 0)        {            if (isValue && !isKey && !isSection)            {                value[valueIndex] = 0;                std::wstring wKey(key);                std::wstring wValue(value);                if (sectionTable.size() <= 0)                {                    ++errorRow;                    return errorRow;                }                sectionTable[sectionTable.size() - 1].kValueTable[wKey] = wValue;            }            else if (isKey)            {                ++errorRow;                return errorRow;            }        }        else if (isSection)        {            if (text[i] != _T(' '))            {                if (isKey || isValue)                {                    ++errorRow;                    return errorRow;                }                else                {                    sectionName[sectionIndex] = text[i];                    ++sectionIndex;                }            }        }        else if (isKey)        {            if (text[i] != _T(' '))            {                if (isSection || isValue)                {                    ++errorRow;                    return errorRow;                }                else                {                    key[keyIndex] = text[i];                    ++keyIndex;                }            }        }        else if (isValue)        {            if (text[i] != _T(' '))            {                if (isSection || isKey)                {                    ++errorRow;                    return errorRow;                }                else                {                    value[valueIndex] = text[i];                    ++valueIndex;                }            }        }        else        {            if (text[i] == _T(';'))            {                isComment = true;            }            if (text[i] != _T(' ') && text[i] != 0 && !isComment)            {                isKey = true;                key[keyIndex] = text[i];                ++keyIndex;            }        }    }    if (isValue)    {        value[valueIndex] = 0;        std::wstring wKey(key);        std::wstring wValue(value);        if (sectionTable.size() <= 0)        {            ++errorRow;            return errorRow;        }        sectionTable[sectionTable.size() - 1].kValueTable[wKey] = wValue;    }    if (sectionTable.size() <= 0)    {        return -1;    }    else    {        return 0;    }}std::wstring CIni::ToString(){    std::wstring context;    // 遍历节表    for (auto it = m_sectionTable.begin(); it != m_sectionTable.end(); ++it)    {        context += _T("    [");        context += it->sectionName;        context += _T("]\n");        // 遍历键值表        for (auto i = it->kValueTable.begin(); i != it->kValueTable.end(); ++i)        {            context += _T("    |-- ");            context += i->first;            context += _T(" = ");            context += i->second;            context += _T("\n");        }        context += _T("\n");    }    return context;}

test.cpp

#include <Ini.h>#include <iostream>#include <string>#include <locale>int main(){    CIni ini;    if (0 == ini.Load(_T("test.ini")))    {        std::locale loc("chs");        std::wcout.imbue(loc);        std::wcout << ini.ToString();    }    return 0;}

test.ini

[General]AutoRun=0AutoDownload=0DiskCache=4AutoShutDown=0ShowPortal=0[Category]count=5Default=2Category0=2|4|0|已下载|C:\QQDownload|0Category1=4|0|7|软件|C:\QQDownload\Software|0Category2=7|0|8|音乐|C:\QQDownload\Music|0Category3=8|0|9|游戏|C:\QQDownload\Game|0Category4=9|0|0|电影|C:\QQDownload\Movies|0[TaskInfo]ShowReferPage=http://www.qq.comReferPage=http://www.qq.comDefaultCategory=2UseLastCategory=1LastCategory=2

运行结果
这里写图片描述

原创粉丝点击