INI文件解析、遍历

本文介绍了一个自己编写的INI文件解析器,针对微软API的不便,特别是遍历功能进行了优化。该解析器仅支持Unicode小端编码的INI文件,遵循特定的格式规则,如节名需在中括号内,键值对用等号分隔,并且键值对和节必须分别占据一行。注释以分号开始,空格和不符合规则的字符将被忽略。文章附带了源代码(Ini.h, Ini.cpp, test.cpp, test.ini)及运行结果。" 111959722,10542707,ELK搜索语法详解:掌握核心查询操作,"['Elasticsearch', '搜索语法', 'ELK']
摘要由CSDN通过智能技术生成

工作中时常需要给软件添加配置文件功能,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);

     
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值