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

开发环境: vs2013, win10

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

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

头文件:

/*
	对文本的处理要求:'='号之前强制为整数,且只允许开头后者结尾存在空格(处理后丢弃空格),不允许存在非数字字符,否则将丢弃该键值对
	=号右边的value原样保存,包括空格的存在.
	对于读取多个ini文件,只要修改一下,就是在loadFile函数中不要对m_map进行clear

	已通过的测试样例:
	1									=       abdfadfadfd
	======
	aaaaaa
	vvvv
	a
	123 + 234
	555=
	zzz=
	=dd
	=123
	=567=
	========
	a=1
	1234adfdd
*/
#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 facet
		wFileStream.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下ok
	std::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;
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值