17.18.实现一个读取INI文件的类

来源:互联网 发布:java虚拟机教程 编辑:程序博客网 时间:2024/06/06 21:06

开发环境: vs2013, win10

经过很多次修改,和对一些错误的学习,才搞定了这么一个类:

比如说LPCTSTR的赋值,new和delete要成对出现,字符数组和字符串的库函数去取代自己写字符串处理函数等, wcsncpy_s用法,string类的赋值运算符等。

头文件:

/*对文本的处理要求:'='号之前强制为整数,且只允许开头后者结尾存在空格(处理后丢弃空格),不允许存在非数字字符,否则将丢弃该键值对=号右边的value原样保存,包括空格的存在.对于读取多个ini文件,只要修改一下,就是在loadFile函数中不要对m_map进行clear已通过的测试样例:1=       abdfadfadfd======aaaaaavvvva123 + 234555=zzz==dd=123=567=========a=11234adfdd*/#pragma once#include "stdafx.h"#include<iostream>#include<fstream>#include<windows.h>#include<string>#include<map>class QueryIni{public:QueryIni(){}~QueryIni(){}public:/*** @brief 初始化成员变量指针* @return void*/static void Init();/*** @brief delete成员变量指针* @return void*/static void UnInit();public:/*** @brief 查找ini文件中的键值,必须先调用SetPath,传入路径,再调用GetValue;* @param[in] const int iKey 要查询的键* @return 查找成功返回value字符串,否则返回空字符串*/static std::wstring QueryIni::GetValue(const int iKey){wchar_t sDes[MAX_PATH + 1] = { 0 };QueryIni::_GetInstance()->_GetValue(iKey, sDes, MAX_PATH);   //TRUE,得到查询结果return sDes;}/*** @brief 读取的文件路径* @param[in] LPCTSTR pFilePath 读取的文件的路径* @return 是否成功载入文件内的数据*/static bool LoadFile(LPCTSTR pFilePath);/*** @brief 清空map中的数据*/static void Clear();private:static QueryIni* _GetInstance();bool QueryIni::_RemoveSpaceAndCheckNum(std::wstring &sKey);bool _GetValue(const int iKey, wchar_t* sDes, const int len);private:std::map<int, std::wstring> m_map;static QueryIni* ms_pInstance;};
实现文件:

#include"stdafx.h"#include"QueryIni.h"#include <iostream>  #include <fstream>  #include <string>  #include <codecvt>#include <locale>  #include<assert.h>using namespace std;QueryIni* QueryIni::ms_pInstance = NULL;void QueryIni::Init(){if (ms_pInstance == NULL) {ms_pInstance = new QueryIni();}}void QueryIni::UnInit(){if (ms_pInstance != NULL) {delete ms_pInstance;ms_pInstance = NULL;}}bool QueryIni::LoadFile(LPCTSTR pFilePath){QueryIni* queryIni = QueryIni::_GetInstance();if (pFilePath == NULL){return false;}//这个不一定要哦!std::wifstream wFileStream(pFilePath, std::ios::binary);if (wFileStream.is_open()){wchar_t buf[2] = {0};wFileStream.read(buf, 2);wFileStream.clear();wFileStream.seekg(0, ios::beg);bool isUnicode =  (buf[0] == wchar_t(0xFF) && buf[1] == wchar_t(0xFE)) || (buf[0] == wchar_t(0xFE) && buf[1] == wchar_t(0xFF)) ;assert(isUnicode == true);// apply BOM-sensitive UTF-16 facetwFileStream.imbue(std::locale(wFileStream.getloc(), new std::codecvt_utf16 < wchar_t, 0x10ffff, std::consume_header >));//第二个参数是此平面将读或写而不出错的wchar_t最大值std::wstring wLine;while (std::getline(wFileStream, wLine)){int equalPos = wLine.find_first_of(L'=');//从pos开始查找'='第一次出现的位置std::wstring sKey = L"", sValue = L"";if (equalPos != wstring::npos){sKey = wLine.substr(0, equalPos);sValue = wLine.substr(equalPos + 1, wLine.length() - equalPos);if (queryIni->_RemoveSpaceAndCheckNum(sKey))//键合法,插入map{int iKey = stoi(sKey);queryIni->m_map.insert(make_pair(iKey, sValue));}}}wFileStream.close();//打开完文件记得关闭return true;}return false;}void QueryIni::Clear(){QueryIni::_GetInstance()->m_map.clear();}QueryIni* QueryIni::_GetInstance(){if (ms_pInstance == NULL){ms_pInstance = new QueryIni();}return ms_pInstance;}bool QueryIni::_RemoveSpaceAndCheckNum(std::wstring &sKey){sKey.erase(0, sKey.find_first_not_of(L" \t"));sKey.erase(sKey.find_last_not_of(L" \t") + 1);if (sKey == L"")//这是个空字符串{return false;}for (int i = 0; i < sKey.size(); i++){if (sKey[i] > L'9' || sKey[i] < L'0'){return false;}}return true;}bool QueryIni::_GetValue(const int iKey, wchar_t* sDes, const int len){std::map<int, std::wstring>::iterator it = m_map.find(iKey);if (it == m_map.end()){return false;                             //不存在}else{std::wstring sValue = it->second;assert(sValue.length() < len);//小心长度溢出wcsncpy_s(sDes, len, &(sValue[0]), sValue.length());return true;}}

至于QueryIni::GetValue(const int iKey)函数为什么放在头文件而不是在实现文件中,参考:Windows跨模块内存管理的浅薄理解

使用的main函数:

#include "stdafx.h"#include<iostream>#include<fstream>#include<windows.h>#include<string>#include<map>#include <codecvt>#include"QueryIni.h"using namespace std;int _tmain(int argc, _TCHAR* argv[]){QueryIni::Init();QueryIni::LoadFile(L"C:\\Users\\admin\\Desktop\\test2.ini");std::locale loc("chs");//windows下okstd::wcout.imbue(loc);std::wcout << QueryIni::GetValue(1) << std::endl;std::wcout << QueryIni::GetValue(100152) << std::endl;std::wcout << QueryIni::GetValue(102004) << std::endl;std::wcout << QueryIni::GetValue(102054) << std::endl;std::wcout << QueryIni::GetValue(100165) << std::endl;QueryIni::UnInit();{return 0;}









原创粉丝点击