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 §ionTable); // 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
运行结果
阅读全文
2 0
- INI文件解析、遍历
- VC遍历INI文件
- VC遍历INI文件
- Ini文件遍历
- python 解析ini 文件
- ini文件解析器
- php解析.ini文件
- INI文件解析类
- shell解析ini文件
- python解析ini文件
- shell解析ini文件
- ini文件解析器
- Java解析INI文件
- node解析ini文件
- Go-ini文件解析
- Python解析INI文件
- ini文件解析中的STL
- C# ini 文件解析库
- unity万能的提示窗口
- 阿里云RDC自动化测试和持续集成服务上线
- 支持存储重复数值的位图
- HDU 2014
- 搭建LNMP环境
- INI文件解析、遍历
- 一个简单的mock例子
- 【自学笔记】活动被收回怎么办?
- 厌倦了Windows(/ `. `/)新手上手Centos7
- Angular 学习总结笔记
- pandas入门——创建series
- Spark学习总结一 单词计数
- git 还原到某次commit
- 获取手机联系人信息 很简单的方法