1. 程式人生 > >MFC讀寫配置檔案

MFC讀寫配置檔案

##這是一個讀寫配置檔案的類

  • .h檔案
#pragma once
#include <wtypes.h>
#include <afxstr.h>
#include <afxcoll.h>

//配置檔案類    讀寫ini配置檔案

/*
設定配置檔案路徑位置在GetAppdataDir()函式中
*/

class CConfigFile
{
public:
	CConfigFile(void);
	~CConfigFile(void);
	//配置檔案主要分為三部分:欄位名	鍵名	鍵值

public:
	static CConfigFile& instance
(); public: BOOL SetFileName(LPCTSTR lpFileName); //設定檔案路徑 CString GetFileName(void); //獲得檔案路徑 //讀取鍵值 CString GetAt(LPCTSTR szSection, LPCTSTR szName, LPCTSTR szDefault = nullptr) const; int GetAt(LPCTSTR szSection, LPCTSTR szName, int nDefault) const; double GetAt(LPCTSTR szSection, LPCTSTR szName,
double fDefault) const; //寫入鍵值 void SetAt(LPCTSTR szSection, LPCTSTR szName, LPCTSTR szValue); void SetAt(LPCTSTR szSection, LPCTSTR szName, int value); void SetAt(LPCTSTR szSection, LPCTSTR szName, double value); BOOL DelSection(LPCTSTR lpSection);//刪除欄位 BOOL DelKey(LPCTSTR lpSection, LPCTSTR lpKey)
; //刪除某一欄位下的鍵名 CString GetValue(LPCTSTR lpSection, LPCTSTR lpKey); //得到某一欄位下某一鍵名的鍵值. BOOL SetValue(LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpValue,bool bCreate = true);//設定鍵值,bCreate是指段名及鍵名未存在時,是否建立 int GetSections(CStringArray& arrSection);//得到全部的段名 int GetKeyValues(int& nCount,CStringArray& arrKey,CStringArray& arrValue, LPCTSTR lpSection);//得到欄位下鍵的總數、鍵名、和鍵值 BOOL DelAllSections();//刪除所有的欄位 private: CString GetIniValue(LPCTSTR section, LPCTSTR valueName, LPCTSTR sz_default) const; void SetIniValue(LPCTSTR section, LPCTSTR valueName, LPCTSTR value); bool IsStartOfOne(LPCTSTR sz, LPCTSTR beg); bool IsEndOfOne(LPCTSTR sz, LPCTSTR end); CString Combine(LPCTSTR szPath1, LPCTSTR szPath2); CString GetAppdataDir();//使用者資訊目錄 private: CString m_strAppdataFile; // 放置在appdata目錄下 }; #define G_ConfigFile (CConfigFile::instance())
  • .cpp檔案
#include "StdAfx.h"
#include "ConfigFile.h"
#include <shlobj.h>

#define MAX_ALLKEYS 6000  //全部的鍵名
#define MAX_KEY 260  //一個鍵名長度
#define MAX_ALLSECTIONS 2048  //全部的段名
#define MAX_SECTION 260  //一個段名長度

CConfigFile::CConfigFile(void)
{
	m_strAppdataFile = GetAppdataDir();
}


CConfigFile::~CConfigFile(void)
{
}

CConfigFile& CConfigFile::instance()
{
	static CConfigFile inst;
	return inst;
}

BOOL CConfigFile::SetFileName( LPCTSTR lpFileName )
{
	CFile file;
	CFileStatus status;
	if(!file.GetStatus(lpFileName,status))
		return TRUE;
	m_strAppdataFile = lpFileName;
	return FALSE;
}

CString CConfigFile::GetFileName( void )
{
	return m_strAppdataFile;
}

CString CConfigFile::GetAt( LPCTSTR szSection, LPCTSTR szName, LPCTSTR szDefault /*= nullptr*/ ) const
{
	return GetIniValue(szSection, szName, szDefault);
}

int CConfigFile::GetAt( LPCTSTR szSection, LPCTSTR szName, int nDefault ) const
{
	TCHAR sz[10];
	_itot_s(nDefault, sz, 10);
	const auto result = GetIniValue(szSection, szName, sz);
	return _ttoi(result);
}

double CConfigFile::GetAt( LPCTSTR szSection, LPCTSTR szName, double fDefault ) const
{
	CString strDefault;
	strDefault.Format(_T("%G"), fDefault);

	const auto result = GetIniValue(szSection, szName, strDefault);
	return _ttof(result);
}

void CConfigFile::SetAt( LPCTSTR szSection, LPCTSTR szName, LPCTSTR szValue )
{
	SetIniValue(szSection, szName, szValue);
}

void CConfigFile::SetAt( LPCTSTR szSection, LPCTSTR szName, int value )
{
	TCHAR sz[10];
	_itot_s(value, sz, 10);
	SetIniValue(szSection, szName, sz);
}

void CConfigFile::SetAt( LPCTSTR szSection, LPCTSTR szName, double value )
{
	CString strValue;
	strValue.Format(_T("%G"), value);
	SetIniValue(szSection, szName, strValue);
}

BOOL CConfigFile::DelSection( LPCTSTR lpSection )
{
	if(WritePrivateProfileString(lpSection,NULL,NULL,m_strAppdataFile))
		return FALSE;
	else
		return GetLastError();
}

BOOL CConfigFile::DelKey( LPCTSTR lpSection, LPCTSTR lpKey )
{
	if(WritePrivateProfileString(lpSection,lpKey,NULL,m_strAppdataFile))
		return FALSE;
	else
		return GetLastError();
}

CString CConfigFile::GetValue( LPCTSTR lpSection, LPCTSTR lpKey )
{
	DWORD dValue;
	TCHAR lpValue[MAX_PATH] ={0};

	dValue=GetPrivateProfileString(lpSection,lpKey,_T(""),lpValue,MAX_PATH,m_strAppdataFile);
	return lpValue;
}

BOOL CConfigFile::SetValue( LPCTSTR lpSection, LPCTSTR lpKey, LPCTSTR lpValue,bool bCreate /*= true*/ )
{
	TCHAR lpTemp[MAX_PATH] ={0};

	//以下if語句表示如果設定bCreate為false時,當沒有這個鍵名時則返回TRUE(表示出錯)
	//!*&*none-value*&!* 這是個垃圾字元沒有特別意義,這樣亂寫是防止湊巧相同。
	if (!bCreate)
	{
		GetPrivateProfileString(lpSection,lpKey,_T("!*&*none-value*&!*"),lpTemp,MAX_PATH,m_strAppdataFile);
		if(_tcscmp(lpTemp,_T("!*&*none-value*&!*"))==0)
			return TRUE;
	}

	if(WritePrivateProfileString(lpSection,lpKey,lpValue,m_strAppdataFile))
		return FALSE;
	else
		return GetLastError();
}

int CConfigFile::GetSections( CStringArray& arrSection )
{
	/*
	本函式基礎:
	GetPrivateProfileSectionNames - 從 ini 檔案中獲得 Section 的名稱
	如果 ini 中有兩個 Section: [sec1] 和 [sec2],則返回的是 'sec1',0,'sec2',0,0 ,當你不知道  
	ini 中有哪些 section 的時候可以用這個 api 來獲取名稱 
	*/
	int i;  
	int iPos = 0;  
	int iMaxCount;
	TCHAR chSectionNames[MAX_ALLSECTIONS] = {0}; //總的提出來的字串
	TCHAR chSection[MAX_SECTION] = {0}; //存放一個段名。
	GetPrivateProfileSectionNames(chSectionNames,MAX_ALLSECTIONS,m_strAppdataFile);

	//以下迴圈,截斷到兩個連續的0
	for(i = 0; i < MAX_ALLSECTIONS; i++)
	{
		if (chSectionNames[i] == 0)
			if (chSectionNames[i] == chSectionNames[i+1])
				break;
	}

	iMaxCount = i + 1; //要多一個0號元素。即找出全部字串的結束部分。
	arrSection.RemoveAll();//清空原陣列

	for(i = 0; i < iMaxCount; i++)
	{
		chSection[iPos++] = chSectionNames[i];
		if(chSectionNames[i] == 0)
		{  
			if (chSection != _T(""))
			{
				arrSection.Add(chSection);
			}	
			memset(chSection,0,MAX_SECTION);
			iPos=0;
		}
	}

	return (int)arrSection.GetSize();
}

int CConfigFile::GetKeyValues( int& nCount,CStringArray& arrKey,CStringArray& arrValue, LPCTSTR lpSection )
{
	/*
	本函式基礎:
	GetPrivateProfileSection- 從 ini 檔案中獲得一個Section的全部鍵名及值名
	如果ini中有一個段,其下有 "段1=值1" "段2=值2",則返回的是 '段1=值1',0,'段2=值2',0,0 ,當你不知道  
	獲得一個段中的所有鍵及值可以用這個。 
	*/
	nCount = 0;
	int i = 0;  
	int iPos=0;
	CString strKeyValue;
	int iMaxCount = 0;
	TCHAR chKeyNames[MAX_ALLKEYS]={0}; //總的提出來的字串
	TCHAR chKey[MAX_KEY]={0}; //提出來的一個鍵名

	GetPrivateProfileSection(lpSection,chKeyNames,MAX_ALLKEYS,m_strAppdataFile);

	for(i=0;i<MAX_ALLKEYS;i++)
	{
		if (chKeyNames[i] == 0)
			if (chKeyNames[i] == chKeyNames[i+1])
				break;
	}

	iMaxCount=i+1; //要多一個0號元素。即找出全部字串的結束部分。
	arrKey.RemoveAll();//清空原陣列
	arrValue.RemoveAll();

	for(i=0; i<iMaxCount; i++)
	{
		chKey[iPos++] = chKeyNames[i];
		if(chKeyNames[i] == 0)
		{
			strKeyValue = chKey;
			CString strKey = strKeyValue.Left(strKeyValue.Find(_T('=')));
			if (strKey != _T(""))
			{
				arrKey.Add(strKeyValue.Left(strKeyValue.Find(_T('='))));
				arrValue.Add(strKeyValue.Mid(strKeyValue.Find(_T('='))+1));
				nCount++;
			}
			memset(chKey,0,MAX_KEY);
			iPos = 0;
		}
	}

	return (int)arrKey.GetSize();
}

BOOL CConfigFile::DelAllSections()
{
	int nSection;
	CStringArray arrSection;
	nSection = GetSections(arrSection);
	for(int i = 0; i < nSection; i++)
	{
		if(DelSection(arrSection[i]))
			return GetLastError();
	}
	return FALSE;
}

CString CConfigFile::GetIniValue( LPCTSTR section, LPCTSTR valueName, LPCTSTR sz_default ) const
{
	CString value;
	auto dwRs = ::GetPrivateProfileString(section, valueName, sz_default, value.GetBuffer(256), 256, m_strAppdataFile);
	value.ReleaseBuffer();
	if (0x2 != GetLastError())
	{
		// 成功
		return value;
	}

	return value = sz_default;
}

void CConfigFile::SetIniValue( LPCTSTR section, LPCTSTR valueName, LPCTSTR value )
{
	::WritePrivateProfileString(section, valueName, value, m_strAppdataFile);
}

bool CConfigFile::IsStartOfOne( LPCTSTR sz, LPCTSTR beg )
{
	if (nullptr == sz || _T('\0') == *sz)
	{
		return false;
	}

	for (auto p = beg; nullptr != p && _T('\0') != *p; ++p)
	{
		if (*sz == *p)
		{
			return true;
		}
	}

	return false;
}

bool CConfigFile::IsEndOfOne( LPCTSTR sz, LPCTSTR end )
{
	if (nullptr == sz || _T('\0') == *sz)
	{
		return false;
	}

	auto p = sz + _tcslen(sz) - 1;
	for (auto pEnd = end; pEnd != nullptr && _T('\0') != *pEnd; pEnd++)
	{
		if (*pEnd == *p)
		{
			return true;
		}
	}

	return false;
}

CString CConfigFile::Combine( LPCTSTR szPath1, LPCTSTR szPath2 )
{
	CString result = szPath1;
	bool bPath1EndHas = IsEndOfOne(szPath1, _T("/\\"));
	bool bPath2Start = IsStartOfOne(szPath2, _T("\\/"));
	if (bPath1EndHas&&bPath2Start)
	{
		result += szPath2 + 1;
	}
	else if (!bPath1EndHas && !bPath2Start)
	{
		result += _T('\\');
		result += szPath2;
	}
	else
	{
		result += szPath2;
	}

	return result;
}

CString CConfigFile::GetAppdataDir()
{
	TCHAR szPath[_MAX_PATH];
	::SHGetSpecialFolderPath(nullptr, szPath, CSIDL_APPDATA, TRUE);//得到的是C盤中:C:\Users\17621\AppData\Roaming下的目錄
	CString strDir = Combine(szPath, _T("\\WT"));
	::CreateDirectory(strDir, nullptr);

	strDir = Combine(strDir, _T("Datas"));
	::CreateDirectory(strDir, nullptr);
	return strDir;
}