现在的位置: 首页 > 综合 > 正文

ini文件另一种读取办法

2012年06月25日 ⁄ 综合 ⁄ 共 7104字 ⁄ 字号 评论关闭

Windows下的ini文件的读取可以使用系统提供的api来实现

GetPrivateProfileString

GetPrivateProfileInt

...

实际应用中, 如果不使用一种统一的方法来包装一下会让源代码看起来很乱。

所以,需要设计一个方便,美观,直观的配置文件操作类!

原则是代码好看,容易维护

需求:

直观的调用形式

实现潜规则

满足各类数据(实现api常用的数据类型)

解释:
  • 直观的调用形式是什么意思
    以减少键盘输入和见文知意为原则的设计方式,把长函数名变为符号。用符号来表示操作
  • 潜规则
    在配置ini访问中的潜规则是
    1. Wiki上对ini的定义
        INI文件有节的概念节用 [] 包围,类似数据中的表名称,如
    [startup]

        名称/值对,类似数据库表中的字段,如

    TargetIP=10.0.0.1

        注释, 以";"为注释的开始,到行尾,如

    MenuOne=File...    ; 菜单的第一项文字描述

    2. Windows系统中操作ini文件时有#开头的行是忽略的,如:

    #对打印机的设置

     3. 可配置是否忽略Key的大小写
     4. 符合语义的读取和写入
在windows api下GetPrivateProfile/WritePrivateProfileXXXX在调用该方法时同步执行对ini文件的操作
  • 满足各类数据,在ini中常用的数据有两种,字符串整型数据,满足所有数据类型显然不现实,可以在之后根据不同需要进行扩展
设计使用方法:

1.  读取

CIniAccessor accessor(_T("config.ini"));
std::wstring strMenuOne = accessor[_T("startup")][_T("MenuOne")](_T("DefaultMenuItem"));
2. 写入
CIniAccessor accessor(_T("config.ini"));
accessor[_T("startup")][_T("TargetIP")] = _T("10.0.0.100");

3. 更新

CIniAccessor accessor(_T("config.ini"));
accessor.Update();	// 从磁盘上更新
accessor.Commit();      // 写入磁盘
下面是数据结构
  1. 基础类
    typedef struct tagAccessorData
    {
    	union VALUETYPE
    	{
    		LONG longValue;
    		TCHAR * pszValue;
    	}value;
    	enum{TYPE_EMPTY, TYPE_LONG, TYPE_CHAR}valuetype;
    	tagAccessorData():valuetype(TYPE_EMPTY){}
    }ACCESSORDATA;

  2. 辅助工具类
    
    
    class CCoAccessorImpl:public ACCESSORDATA
    {
    private:	
    	TCHAR m_szTemp[30];	
    public:
    	CCoAccessorImpl()
    	{
    		valuetype = TYPE_EMPTY;
    		value.longValue = 0;
    	}
    	CCoAccessorImpl(const CCoAccessorImpl & acc)
    	{
    		valuetype = acc.valuetype;
    		if(acc.valuetype == TYPE_CHAR)
    		{
    			value.pszValue = new TCHAR[_tcslen(acc.value.pszValue) + 1];
    			ZeroMemory(value.pszValue, sizeof(TCHAR) * (_tcslen(acc.value.pszValue) + 1));
    			_tcscpy(value.pszValue, acc.value.pszValue);
    		}else
    		{
    			value.longValue = acc.value.longValue;
    		}
    	}
    	CCoAccessorImpl(const LONG lValue)
    	{
    		valuetype = TYPE_LONG;
    		value.longValue = lValue;
    	}
    	CCoAccessorImpl(LPCTSTR lpszValue)
    	{
    		valuetype = TYPE_CHAR;
    		value.pszValue = new TCHAR[_tcslen(lpszValue) + 1];
    		ZeroMemory(value.pszValue, sizeof(TCHAR) * (_tcslen(lpszValue) + 1));
    		_tcscpy(value.pszValue, lpszValue);
    	}
    	~CCoAccessorImpl()
    	{
    		if(valuetype == TYPE_CHAR) delete [] value.pszValue;
    	}
    
    
    	CCoAccessorImpl & operator = (const CCoAccessorImpl& acc)
    	{
    		if(valuetype == TYPE_CHAR) delete [] value.pszValue;
    		value.longValue = 0;
    		valuetype = acc.valuetype;
    		if(acc.valuetype == TYPE_CHAR)
    		{
    			value.pszValue = new TCHAR[_tcslen(acc.value.pszValue) + 1];
    			ZeroMemory(value.pszValue, sizeof(TCHAR) * (_tcslen(acc.value.pszValue) + 1));
    			_tcscpy(value.pszValue, acc.value.pszValue);
    		}else
    		{
    			value.longValue = acc.value.longValue;
    		}
    		return *this;
    	}
    	CCoAccessorImpl & operator = (const LONG lValue)
    	{
    		if(valuetype == TYPE_CHAR) delete [] value.pszValue;
    		valuetype = TYPE_LONG;
    		value.longValue = lValue;
    		return *this;
    	}
    
    
    	CCoAccessorImpl & operator = (LPCTSTR lpszValue)
    	{
    		if(valuetype == TYPE_CHAR) delete [] value.pszValue;
    
    
    		valuetype = TYPE_CHAR;
    		value.pszValue = new TCHAR[_tcslen(lpszValue) + 1];
    		ZeroMemory(value.pszValue, sizeof(TCHAR) * (_tcslen(lpszValue) + 1));
    		_tcscpy(value.pszValue, lpszValue);
    		return *this;
    	}
    
    
    	
    	operator LPCTSTR ()
    	{		
    		switch(valuetype)
    		{		
    		case TYPE_LONG: return _ltot(value.longValue, m_szTemp, 10);
    		case TYPE_CHAR: return value.pszValue;
    		}
    		return _T("");
    	}
    	
    	operator LONG ()
    	{		
    		switch(valuetype)
    		{
    		case TYPE_LONG:
    		case TYPE_EMPTY:
    			return value.longValue;
    		}
    		return _ttol(value.pszValue);
    	}
    	CCoAccessorImpl operator ()(LPCTSTR lpsz) //default value
    	{
    		if(valuetype == TYPE_EMPTY) return CCoAccessorImpl(lpsz);
    		return *this;
    	}
    	CCoAccessorImpl operator ()(LONG lValue) //default value
    	{
    		if(valuetype == TYPE_EMPTY) return CCoAccessorImpl(lValue);
    		return *this;
    	}
    
    
    
    
    };
    typedef std::basic_string<TCHAR> TCharArray;
    
    
    
    
    struct less
    {
    	bool operator()(const TCharArray& _Left, const TCharArray& _Right) const
    	{	
    		return _tcsicmp(_Left.c_str(), _Right.c_str()) < 0;
    	}
    };
    
    
    
    
    template<class ValueType, BOOL bSensitive>
    class CKeyValueArray:public std::map<TCharArray, ValueType, less>
    {	
    public:
    	CKeyValueArray(){}
    	~CKeyValueArray(){}
    	ValueType & operator[](TCharArray charArray)
    	{
    		if(!bSensitive) _tcsupr((TCHAR*)charArray.data());
    		return std::map<TCharArray, ValueType, less>::operator[](charArray);
    	}
    };
    // 读文件操作
    template<class Storage>
    struct iniparser
    {
    	BOOL operator()(Storage & store, LPCTSTR lpszFilePath)
    	{
    		HANDLE hFile = CreateFile(lpszFilePath,               // file to open
    			GENERIC_READ,          // open for reading
    			FILE_SHARE_READ,       // share for reading
    			NULL,                  // default security
    			OPEN_EXISTING,         // existing file only
    			FILE_ATTRIBUTE_NORMAL, // normal file
    			NULL);                 // no attr. template
    
    
    		if (hFile == INVALID_HANDLE_VALUE) 
    		{ 			
    			return FALSE; 
    		}
    
    
    		TCHAR sz[2] = {0};
    		DWORD dwRead = 0;
    		TCharArray tcaLine;
    		TCharArray tcaSectionName;
    		struct foo
    		{
    			static void parse(Storage & store, TCharArray & tcaSectionName, TCharArray & tcaLine)
    			{
    				if(!tcaLine.size()) return;
    				// parse []
    				TCHAR szComment[MAX_PATH] = {0};
    				if(tcaLine.at(0) == _T('#')) return;
    
    
    				TCharArray sSec;
    				if(_stscanf(tcaLine.c_str(), _T("[%[^]]]"), (TCHAR*)sSec.assign(MAX_PATH,0).data()))
    				{
    					tcaSectionName = sSec;
    				}
    				else
    				{
    					// parse key = value
    					TCHAR szKey[MAX_PATH] = {0};
    					TCHAR szValue[MAX_PATH] = {0};
    					if(2 == _stscanf(tcaLine.c_str(), _T("%[^=]=%[^\0]"), szKey, szValue))					
    					{
    						store[tcaSectionName][szKey] = szValue;
    					}
    				}
    
    
    			}
    		};
    		while(ReadFile(hFile, sz, sizeof(TCHAR),&dwRead, NULL))
    		{
    			if(!dwRead) break;
    			if(!(sz[0] == _T('\r') || sz[0] == _T('\n'))) 
    			{
    				tcaLine.push_back(sz[0]);
    				continue;
    			}
    			
    				foo::parse(store, tcaSectionName, tcaLine);
    			tcaLine.clear();
    			tcaLine.reserve();			
    		}
    		CloseHandle(hFile);
    		foo::parse(store, tcaSectionName, tcaLine);	
    
    
    		return TRUE;
    	}
    };
    // 写文件操作
    template<class Storage>
    struct inipersistor
    {
    	BOOL operator()(Storage & store, LPCTSTR lpszFilePath)
    	{
    		HANDLE hFile = CreateFile(lpszFilePath,               // file to open
    			GENERIC_WRITE,          // open for reading
    			FILE_SHARE_WRITE,       // share for reading
    			NULL,                  // default security
    			OPEN_ALWAYS,         // existing file only
    			FILE_ATTRIBUTE_NORMAL, // normal file
    			NULL);                 // no attr. template
    
    
    		if (hFile == INVALID_HANDLE_VALUE) 
    		{ 			
    			return FALSE; 
    		}
    
    
    		for(Storage::iterator it = store.begin();it != store.end();it++)
    		{
    			TCharArray tcaSectionName = (*it).first;
    			Storage::mapped_type & kva = (*it).second;
    			DWORD dwWritten = 0;
    			WriteFile(hFile, _T("["), sizeof(TCHAR), &dwWritten, NULL);			
    			WriteFile(hFile, tcaSectionName.c_str(), sizeof(TCHAR) * tcaSectionName.size(), &dwWritten, NULL);
    			WriteFile(hFile, _T("]\r\n"), sizeof(TCHAR) * 3, &dwWritten, NULL);
    			for(Storage::mapped_type::iterator itKeyVal = kva.begin();itKeyVal != kva.end();itKeyVal++)
    			{
    				TCharArray tcaKey = (*itKeyVal).first;
    				TCharArray tcaVal = (*itKeyVal).second;
    				WriteFile(hFile, tcaKey.c_str(), sizeof(TCHAR) * tcaKey.size(), &dwWritten, NULL);
    				WriteFile(hFile, _T("="), sizeof(TCHAR), &dwWritten, NULL);		
    				WriteFile(hFile, tcaVal.c_str(), sizeof(TCHAR) * tcaVal.size(), &dwWritten, NULL);
    				WriteFile(hFile, _T("\r\n"), sizeof(TCHAR) * 2, &dwWritten, NULL);
    			}
    
    
    		}
    		CloseHandle(hFile);
    		return TRUE;
    	}
    };
  3. 访问类
    template<
    	class ValueType = CCoAccessorImpl, 	
    	BOOL bSensitive = FALSE,
    	class Parser  = iniparser<std::map<TCharArray, CKeyValueArray<ValueType,bSensitive>,less > >,
    	class Persistor = inipersistor<std::map<TCharArray, CKeyValueArray<ValueType,bSensitive>,less > >  
    >
    class TIniAccessor
    {
    public:
    	
    private:
    	Parser _parser;
    	Persistor _persistor;
    	TCharArray m_szFileName;
    public:
    	TIniAccessor(LPCTSTR lpsz):_parser(Parser()),_persistor(Persistor())
    	{
    		m_szFileName = lpsz;
    		_parser(m_sectionarray, m_szFileName.c_str());
    	}
    	BOOL Update()
    	{
    		return _parser(m_sectionarray, m_szFileName.c_str());
    	}
    	BOOL Commit(LPCTSTR lpszSaveIniFile = NULL)
    	{
    		TCharArray tca = m_szFileName;
    		if(lpszSaveIniFile) tca = lpszSaveIniFile;
    
    		return _persistor(m_sectionarray, tca.c_str());
    	}
    	~TIniAccessor(){}	
    private:	
    	typedef std::map<TCharArray, CKeyValueArray<ValueType,bSensitive>, less> SectionArray;
    	SectionArray m_sectionarray;
    public:	
    	CKeyValueArray<ValueType,bSensitive> & operator [](TCharArray charArray)
    	{
    		if(!bSensitive) _tcsupr((TCHAR*)charArray.data());
    		return m_sectionarray[charArray];
    	}
    };
  4. 访问类
    typedef TIniAccessor<> CIniAccessor;


抱歉!评论已关闭.