1. 程式人生 > >17.18.實現一個讀取INI檔案的類

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;
}


相關推薦

17.18.實現一個讀取INI檔案

開發環境: vs2013, win10 經過很多次修改,和對一些錯誤的學習,才搞定了這麼一個類: 比如說LPCTSTR的賦值,new和delete要成對出現,字元陣列和字串的庫函式去取代自己寫字串處理函式等, wcsncpy_s用法,string類的賦值運算子等。 標頭檔案

Linux下讀取Ini檔案

#include "Ini.h" /****************************************************************************** * 功 能:建構函式 * 參 數:無 * 返回值:無 * 備 注: *********************

【java】 一個讀取配置檔案

/** * <p>Title:InitConfig.java</p> * <p>Description:</p> * @author songrongkai * @date 2018年7月29日 * @version 1.0 */ p

伺服器公共庫開發--讀取ini檔案格式的

/********************************************************************    created:    2008/07/28    filename:     config.h    author:        Lichuang       

c語言實現讀取ini檔案操作

二、實現檔案 //ini.c #include "ini.h" #include <string.h> #include <stdio.h> content* pContent; char gfilename[255]; void iniGetInt(const char* lpSe

CIniFile讀取INI檔案

2008年04月26日 星期六 上午 10:27/*=================================================================== 檔名:CIniFile類定義檔案                            

自定義讀取配置檔案

#include<iostream> #include<string.h> #include<vector> #include<map> #include<set> #include <fstream> #include<

C# 操作INI檔案

    //補充:        //using System;     //using System.Runtime.InteropServices;     //using System.Text;     //using System.Collections;    

LayaBox開發實戰之實現一個簡單的模板

tom image nbu tex 技術分享 info fig utils gre 1.首先UI設計:記得導出 2.然後查看layaUI.max.all.js中是否生成對應UI的JS代碼: var FeedBackUI=(function(_super){

Ftp實現自動讀取本地檔案上傳到伺服器

需求:最近有個需求,類似需要將pre環境的oracle檔案,放到prd環境中hive叢集中儲存,但是因為資料來源和資料儲存節點不在一個環境中,所以無法通訊配置實現資料的直接傳輸。 解決方案:  1.寫指令碼自動將oracle中資料寫入到本地指定資料夾。  2.通過

內部類實現多繼承(內部類的優勢)及內部類實現一個介面與外圍實現這個介面的區別

在java中一個類可以多重實現,但不能多重繼承,也就是說一個類能夠同時實現多個介面,但不能同時繼承多個類。但有時候我們確實需要繼承多個類,比如希望擁有兩個類的行為功能,就很難使用單繼承來解決問題了(當然多層繼承是可以解決的),那麼我們還可以用什麼辦法來解決多重繼承的問題呢?沒

內部類實現一個介面與外圍實現這個介面的區別

在java中,外圍類只能繼承一個基類,要實現多繼承,只有繼承多個介面型別。有時,你需要與介面的實現進行互動,所以使用內部類最重要的一個原因是:每個內部類都能獨立的繼承自一個(介面的)實現,內部類允許你繼承多個非介面型別。正是因為內部類的這種能力,有效的實現了“多重繼承”。

使用共享記憶體實現一個程序寫檔案,兩個程序讀檔案

主要功能:讀取任意的檔案,大小不限(不超過共享記憶體設定的大小,一般為8k,但可手動重新設定,這已經很大了。),執行後兩個或多個讀程序可同時讀取該檔案並在終端列印。 要實現該功能,首先你得了解共享記憶體的搭建,有四個函式,分別為shmget,shmat,shmdt,shmc

C#操作Ini檔案

      在Windows系統中,INI檔案是很多,最重要的就是“System.ini”、“System32.ini”和“Win.ini”。該檔案主要存放使用者所做的選擇以及系統的各種引數。使用者可以通過修改INI檔案,來改變應用程式和系統的很多配置。但自從Windows

c# 賬號密碼加密, 寫入讀取ini檔案

[DllImport("kernel32")] private static extern int GetPrivateProfileString(string section, string key, string def, StringBu

用C++實現一個二叉樹

/**//** 昨天參加宜搜的筆試,要求用C++寫一二叉樹類,實現插入,刪除,定位功能,輾轉再三,* 卻無從下手,甚急,終基礎不好,今天再想,通過層次遍歷二叉樹,再進行實現相關功能* 實也不難. 以下程式碼*//**//** FileName:BTree.cpp* Description:binary tre

Java讀取ini檔案的值

IniFile iniFile=new BasicIniFile(); File f = new File(""); String cf = null; cf = f.getCanonicalPath(); File file=new File(c

SpringMVC 實現POI讀取Excle檔案中資料匯入資料庫(上傳)、匯出資料庫中資料到Excle檔案中(下載)

package com.shiliu.game.utils; import java.io.OutputStream; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import

用Python實現一個簡單的檔案傳輸協議

寫個東西並非無聊或者練手,而是厭煩了每次都得重頭寫。我已經不是第一次碰到下面的情況:遠端到一臺可以連線內網的機器,結果發現其環境極為惡劣,沒有scp。最誇張的一次,我見過一臺機器連man都沒裝。所幸裝了ssh可以讓我遠端。但沒有scp怎麼傳檔案呢?ftp?試了幾個命令,沒有

Python實現一個二叉樹

最近在學習Python,之前只是在寫指令碼,做一些資料處理的工作,今天開始看Python的面向物件,熟悉了語法之後,想實現一個二叉樹類練練手。 以前寫C++比較多,用Python寫二叉樹好不習慣,沒有指標,沒有引用!!! 所以我就遇到了一下幾個問題: 1、該怎麼把二叉樹各