//========================================================================
//TITLE:
// Wince读取ini的CIniParse类
//AUTHOR:
// norains
//DATE:
// Monday 22-December-2008
//Environment:
// WINCE5.0 + VS2005 + ARM BSP
//========================================================================
挺奇怪的是,微软在wince中没有像桌面系统般有读取ini的特定函数。为了解决该问题,网上有不少牛人都给给出了相应的解决方案,比如说:
benkaoya的直接C++/C代码读写:http://blog.youkuaiyun.com/benkaoya/archive/2008/01/28/2070648.aspx
xumercury的将以上函数封装为类:http://blog.youkuaiyun.com/xumercury/archive/2008/07/09/2629346.aspx
khan的STL读写类:http://www.cppblog.com/Khan/archive/2007/08/09/29459.html?opt=admin
不过,以上的这几个都有一些小问题,或是效率较低,或是有一些小bug,其实最引起自己重写冲动的是因为命名规则和自己的理念有冲突,所以索性就自己另起炉灶弄了个CIniParse。因为习惯问题,我的代码基本上充斥的是STL代码,如果不喜欢这风格,可以使用benkaoya或xumercury的作品,他们的这个代码也是比较成熟的;关于khan的LIniFile类,在他blog的留言中,似乎公布的这个类代码是有缺陷的,完整的代码需要发信向其索取。因为我没有他的完整版代码,所以我也不做更多的评论。
写完这段有损人利己嫌疑的言语后,我们来看看今天的主角:CIniParse。之前说了别人的代码的缺陷,现在也该说说CIniParse所存在的一些问题了。可能最让人不爽的是,CIniParse类在保存的时候,会将原来的注释全部清除掉,并且原来的顺序也全部重排。如果注释以及顺序对你非常重要,请勿使用CIniParse类。
除此以外,该类并不能在ASCII环境中编译通过。只是wince是UNICODE的系统,所以这点在平时使用中倒不会引起很大的麻烦。当然,如果你是打算移植到VC6.0中,那么可能有一些函数就必须要修正了。再一点就是,该类没有详细地进行测试,所以应该还会有或多或少的问题,如果你发现了,也希望我更正,期待你的指出。
惯例,先罗列出CIniParse的完整代码:
头文件:
- //ClassName
- //CIniParse
- //
- //Version:
- //1.0.0
- //
- //Date:
- //2008.12.22
- //
- //Author:
- //norains
- //
- #pragmaonce
- #include"windows.h"
- #include<string>
- #include<vector>
- #include<map>
- #ifdefUNICODE
- #ifndefTSTRING
- #defineTSTRINGstd::wstring
- #endif
- #else
- #ifndefTSTRING
- #defineTSTRINGstd::string
- #endif
- #endif
- classCIniParse
- {
- public:
- //-------------------------------------------------------------------------------
- //Description:
- //Opentheinifile.
- //-------------------------------------------------------------------------------
- BOOLOpen(TSTRINGstrFile);
- //-------------------------------------------------------------------------------
- //Description:
- //Gettheprofilevalueasstringtype
- //-------------------------------------------------------------------------------
- TSTRINGGetPrivateProfileString(constTSTRING&strSection,constTSTRING&strKey);
- //-------------------------------------------------------------------------------
- //Description:
- //Gettheprofilevalueasinttype
- //-------------------------------------------------------------------------------
- intGetPrivateProfileInt(constTSTRING&strSection,constTSTRING&strKey);
- //-------------------------------------------------------------------------------
- //Description:
- //Settheprofilevalueasstringtype.Thefunctionwouldn'tsavethedatatofile
- //butmemory.Ifyouwanttosavetothefile,youmustcallFlushfunction
- //-------------------------------------------------------------------------------
- BOOLSetPrivateProfileString(constTSTRING&strSection,constTSTRING&strKey,TSTRINGstrSet);
- //-------------------------------------------------------------------------------
- //Description:
- //Settheprofilevalueasinttype.Thefunctionwouldn'tsavethedatatofile
- //butmemory.Ifyouwanttosavetothefile,youmustcallFlushfunction
- //-------------------------------------------------------------------------------
- BOOLSetPrivateProfileInt(constTSTRING&strSection,constTSTRING&strKey,intiSet);
- //-------------------------------------------------------------------------------
- //Description:
- //Flushthememorybuffertothefile
- //-------------------------------------------------------------------------------
- BOOLFlush();
- public:
- CIniParse();
- virtual~CIniParse();
- private:
- //-------------------------------------------------------------------------------
- //Description:
- //Getthelinevaluebaseonthecurrentoffset.Aftercalling,theoffsetvalue
- //wouldmovetotheheadofnextline
- //-------------------------------------------------------------------------------
- TSTRINGGetLine();
- //-------------------------------------------------------------------------------
- //Description:
- //Checkthestringvalueofonelinewhetheriscommentornot
- //-------------------------------------------------------------------------------
- staticBOOLIsCommentLine(constTSTRING&strLine);
- //-------------------------------------------------------------------------------
- //Description:
- //Checkthestringvalueofonelinewhetheristhesection.
- //Parameters:
- //strLine:[in]Thestringvaluebuffer.
- //-------------------------------------------------------------------------------
- staticBOOLIsSectionLine(constTSTRING&strLine);
- //-------------------------------------------------------------------------------
- //Description:
- //Getthekeyvaluefromoneline
- //Parameters:
- //strLine:[in]Thebuffertofind
- //-------------------------------------------------------------------------------
- staticTSTRINGGetKeyValueFromLine(constTSTRING&strLine);
- //-------------------------------------------------------------------------------
- //Description:
- //Getthekeynamefromoneline
- //Parameters:
- //strLine:[in]Thebuffertofind
- //-------------------------------------------------------------------------------
- staticTSTRINGGetKeyNameFromLine(constTSTRING&strLine);
- //-------------------------------------------------------------------------------
- //Description:
- //Getthesectionnamefromoneline
- //Parameters:
- //strLine:[in]Thebuffertofind
- //-------------------------------------------------------------------------------
- staticTSTRINGGetSectionNameFromLine(constTSTRING&strLine);
- //-------------------------------------------------------------------------------
- //Description:
- //Removethespacefromthestring
- //Parameters:
- //strBuf:[in]Thebuffertoremove
- //ReturnValue:
- //Returnthestringwithoutspace
- //-------------------------------------------------------------------------------
- staticTSTRINGRemoveSpace(constTSTRING&strBuf);
- //-------------------------------------------------------------------------------
- //Description:
- //Parsetheinifile
- //-------------------------------------------------------------------------------
- voidParse(constTSTRING&strBuf);
- //-------------------------------------------------------------------------------
- //Description:
- //Convertthestringtolowercase
- //-------------------------------------------------------------------------------
- staticTSTRINGConvertToLowercase(constTSTRING&strBuf);
- //-------------------------------------------------------------------------------
- //Description:
- //Resettheoffsetpointtothebegin
- //-------------------------------------------------------------------------------
- BOOLResetOffset();
- //-------------------------------------------------------------------------------
- //Description:
- //Checkwhethertheoffsetarrivedtheendofthebuffer.
- //-------------------------------------------------------------------------------
- BOOLIsOffsetEnd();
- private:
- TSTRINGm_strFileBuf;
- TSTRING::size_typem_stOffset;
- TSTRINGm_strFilePath;
- std::map<TSTRING,std::map<TSTRING,TSTRING>>m_mpValue;//ThefirstTSTRINGissectionname,thesecondiskeynameandlastisthevalue.
- };
实现体:
- #include"IniParse.h"
- #include<deque>
- #include<algorithm>
- CIniParse::CIniParse():
- m_stOffset(0)
- {}
- CIniParse::~CIniParse()
- {}
- BOOLCIniParse::Open(TSTRINGstrFile)
- {
- HANDLEhFile=CreateFile(strFile.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
- if(hFile==INVALID_HANDLE_VALUE)
- {
- returnFALSE;
- }
- m_strFilePath=strFile;
- DWORDdwSize=GetFileSize(hFile,NULL);
- //Readthefiletobuffer
- std::vector<BYTE>vtBuf(dwSize,0);
- DWORDdwRead=0;
- ReadFile(hFile,&vtBuf[0],vtBuf.size(),&dwRead,NULL);
- vtBuf.resize(dwRead);
- CloseHandle(hFile);
- #ifdefUNICODE
- m_strFileBuf.clear();
- if(vtBuf.size()>=2)
- {
- if(vtBuf[0]==0xFF&&vtBuf[1]==0xFE)
- {
- //Unicodefile
- //Convertthereadbuffertotheunicode.TheTCHARhereisequaltowchar_t
- std::deque<TCHAR>dqBuf;
- for(std::vector<BYTE>::size_typei=2;i<vtBuf.size();i+=2)
- {
- dqBuf.push_back(vtBuf[i]+(vtBuf[i+1]<<8));
- }
- m_strFileBuf.insert(m_strFileBuf.end(),dqBuf.begin(),dqBuf.end());
- }
- else
- {
- std::vector<TCHAR>vtBufT;
- vtBufT.resize(MultiByteToWideChar(CP_ACP,0,reinterpret_cast<char*>(&vtBuf[0]),vtBuf.size(),NULL,0));
- MultiByteToWideChar(CP_ACP,0,reinterpret_cast<char*>(&vtBuf[0]),vtBuf.size(),&vtBufT[0],vtBufT.size());
- m_strFileBuf.insert(m_strFileBuf.end(),vtBufT.begin(),vtBufT.end());
- }
- }
- #else
- #error"Unfortunately!Thesourcecodedonesn'tcompleteintheASCIIenvironment"
- #endif
- Parse(m_strFileBuf);
- returnTRUE;
- }
- TSTRINGCIniParse::GetLine()
- {
- TSTRINGstrReturn;
- if(m_stOffset>=m_strFileBuf.size())
- {
- returnTSTRING();
- }
- TSTRING::size_typestPos=m_strFileBuf.find(TEXT("/r/n"),m_stOffset);
- if(stPos==TSTRING::npos)
- {
- strReturn.insert(0,m_strFileBuf,m_stOffset,m_strFileBuf.size()-m_stOffset+1);
- //Movetheoffsetpositiontoendofthefile
- m_stOffset=m_strFileBuf.size()+1;
- }
- else
- {
- strReturn.insert(0,m_strFileBuf,m_stOffset,stPos-m_stOffset);
- //Movetheoffsetpositiontothebackofthe"/r/n"
- m_stOffset=stPos+2;
- }
- returnstrReturn;
- }
- BOOLCIniParse::IsCommentLine(constTSTRING&strLine)
- {
- if(strLine.empty()!=FALSE||strLine[0]==';')
- {
- returnTRUE;
- }
- else
- {
- returnFALSE;
- }
- }
- BOOLCIniParse::IsSectionLine(constTSTRING&strLine)
- {
- TSTRING::size_typestLeft=strLine.find(TEXT("["));
- TSTRING::size_typestRight=strLine.find(TEXT("]"));
- if(strLine.empty()==FALSE&&stLeft!=TSTRING::npos&&stRight!=TSTRING::npos&&stRight>stLeft)
- {
- returnTRUE;
- }
- else
- {
- returnFALSE;
- }
- }
- TSTRINGCIniParse::GetKeyValueFromLine(constTSTRING&strLine)
- {
- TSTRING::size_typestPosEqual=strLine.find(TEXT("="));
- if(stPosEqual==TSTRING::npos)
- {
- returnTSTRING();
- }
- TSTRINGstrReturn;
- TSTRING::size_typestPosQuoteLeft=strLine.find(TEXT("/""),stPosEqual);
- if(stPosQuoteLeft!=TSTRING::npos)
- {
- TSTRING::size_typestPosQuoteRight=strLine.find(TEXT("/""),stPosQuoteLeft+1);
- if(stPosQuoteRight!=TSTRING::npos&&stPosQuoteLeft+1!=stPosQuoteRight)
- {
- strReturn.insert(0,strLine,stPosQuoteLeft+1,stPosQuoteRight-stPosQuoteLeft-1);
- returnstrReturn;
- }
- }
- //Storethestringtothebuffer
- if(stPosEqual+1>strLine.size())
- {
- returnTSTRING();
- }
- TSTRINGstrBuf(strLine,stPosEqual+1,strLine.size()-stPosEqual);;
- returnRemoveSpace(strBuf);
- }
- TSTRINGCIniParse::GetKeyNameFromLine(constTSTRING&strLine)
- {
- TSTRING::size_typestPosEqual=strLine.find(TEXT("="));
- if(stPosEqual==0)
- {
- returnTSTRING();
- }
- TSTRINGstrBuf;
- if(stPosEqual==TSTRING::npos)
- {
- //Allofthestringlineisthekeyname
- strBuf=strLine;
- }
- else
- {
- strBuf.clear();
- strBuf.insert(0,strLine,0,stPosEqual);
- }
- returnRemoveSpace(strBuf);
- }
- TSTRINGCIniParse::GetSectionNameFromLine(constTSTRING&strLine)
- {
- TSTRING::size_typestLeft=strLine.find(TEXT("["));
- TSTRING::size_typestRight=strLine.find(TEXT("]"));
- if(!(strLine.empty()==FALSE&&stLeft!=TSTRING::npos&&stRight!=TSTRING::npos&&stRight>stLeft))
- {
- returnTSTRING();
- }
- TSTRINGstrBuf(strLine,stLeft+1,stRight-stLeft-1);
- returnRemoveSpace(strBuf);
- }
- TSTRINGCIniParse::RemoveSpace(constTSTRING&strBuf)
- {
- if(strBuf.find(TEXT(""))!=TSTRING::npos)
- {
- //Removethespace
- TSTRINGstrReturn;
- for(TSTRING::size_typestPos=0;stPos<strBuf.size();stPos++)
- {
- if(strBuf[stPos]!='')
- {
- strReturn.push_back(strBuf[stPos]);
- }
- }
- returnstrReturn;
- }
- else
- {
- //Nospace
- returnstrBuf;
- }
- }
- voidCIniParse::Parse(constTSTRING&strBuf)
- {
- //Resetthefilepointertothebegin
- ResetOffset();
- std::map<TSTRING,TSTRING>mpKey;
- TSTRINGstrSection;
- while(TRUE)
- {
- TSTRINGstrLine=GetLine();
- if(strLine.empty()!=FALSE||IsCommentLine(strLine)!=FALSE)
- {
- if(IsOffsetEnd())
- {
- break;
- }
- else
- {
- continue;
- }
- }
- if(IsSectionLine(strLine)!=FALSE)
- {
- if(strSection.empty()!=FALSE)
- {
- //It'sthefirstsection
- strSection=GetSectionNameFromLine(strLine);
- continue;
- }
- //Storethelastsectionvalue
- m_mpValue.insert(std::make_pair(strSection,mpKey));
- strSection=GetSectionNameFromLine(strLine);
- mpKey.clear();
- }
- else
- {
- if(strSection.empty()!=FALSE)
- {
- //Thesectionnameisempty,soneedn'tstorethekeyvalue
- continue;
- }
- //Storethekeyvalueandname
- TSTRINGstrKeyName=GetKeyNameFromLine(strLine);
- if(strKeyName.empty()==FALSE)
- {
- mpKey.insert(std::make_pair(strKeyName,GetKeyValueFromLine(strLine)));
- }
- }
- }
- //Storethelastsectionvalue
- if(strSection.empty()==FALSE)
- {
- m_mpValue.insert(std::make_pair(strSection,mpKey));
- }
- }
- TSTRINGCIniParse::ConvertToLowercase(constTSTRING&strBuf)
- {
- std::vector<TCHAR>vtBuf(strBuf.length()+1,0);
- _tcscpy(&vtBuf[0],strBuf.c_str());
- return_tcslwr(&vtBuf[0]);
- }
- BOOLCIniParse::ResetOffset()
- {
- m_stOffset=0;
- returnTRUE;
- }
- BOOLCIniParse::IsOffsetEnd()
- {
- if(m_stOffset>=m_strFileBuf.size())
- {
- returnTRUE;
- }
- else
- {
- returnFALSE;
- }
- }
- TSTRINGCIniParse::GetPrivateProfileString(constTSTRING&strSection,constTSTRING&strKey)
- {
- if(m_mpValue.empty()!=FALSE)
- {
- returnTSTRING();
- }
- //Ignoringthecharactercasetofindthespecifiedkey
- for(std::map<TSTRING,std::map<TSTRING,TSTRING>>::iteratoriterSection=m_mpValue.begin();iterSection!=m_mpValue.end();iterSection++)
- {
- if(ConvertToLowercase(iterSection->first)==ConvertToLowercase(strSection))
- {
- for(std::map<TSTRING,TSTRING>::iteratoriterKey=iterSection->second.begin();iterKey!=iterSection->second.end();iterKey++)
- {
- if(ConvertToLowercase(iterKey->first)==ConvertToLowercase(strKey))
- {
- returniterKey->second;
- }
- }
- }
- }
- returnTSTRING();
- }
- intCIniParse::GetPrivateProfileInt(constTSTRING&strSection,constTSTRING&strKey)
- {
- return_ttoi(GetPrivateProfileString(strSection,strKey).c_str());
- }
- BOOLCIniParse::SetPrivateProfileString(constTSTRING&strSection,constTSTRING&strKey,TSTRINGstrSet)
- {
- //Ignoringthecharactercasetofindthespecifiedkey
- for(std::map<TSTRING,std::map<TSTRING,TSTRING>>::iteratoriterSection=m_mpValue.begin();iterSection!=m_mpValue.end();iterSection++)
- {
- if(ConvertToLowercase(iterSection->first)==ConvertToLowercase(strSection))
- {
- for(std::map<TSTRING,TSTRING>::iteratoriterKey=iterSection->second.begin();iterKey!=iterSection->second.end();iterKey++)
- {
- if(ConvertToLowercase(iterKey->first)==ConvertToLowercase(strKey))
- {
- iterKey->second=strSet;
- returnTRUE;
- }
- }
- //Addthenewkeyvalue
- iterSection->second.insert(std::make_pair(strKey,strSet));
- returnTRUE;
- }
- }
- //Addthenewsectionandkeyvalue
- std::map<TSTRING,TSTRING>mpKey;
- mpKey.insert(std::make_pair(strKey,strSet));
- m_mpValue.insert(std::make_pair(strSection,mpKey));
- returnTRUE;
- }
- BOOLCIniParse::SetPrivateProfileInt(constTSTRING&strSection,constTSTRING&strKey,intiSet)
- {
- std::vector<TCHAR>vtBuf(MAX_PATH,0);
- TSTRINGstrSet=_itot(iSet,&vtBuf[0],10);
- returnSetPrivateProfileString(strSection,strKey,strSet);
- }
- BOOLCIniParse::Flush()
- {
- TSTRINGstrWrite;
- //strWrite.reserve(m_mpValue.size());
- //Storethestringvaluetothebuffer
- for(std::map<TSTRING,std::map<TSTRING,TSTRING>>::iteratoriterSection=m_mpValue.begin();iterSection!=m_mpValue.end();iterSection++)
- {
- strWrite+=TEXT("/r/n[");
- strWrite+=iterSection->first;
- strWrite+=TEXT("]/r/n");
- for(std::map<TSTRING,TSTRING>::iteratoriterKey=iterSection->second.begin();iterKey!=iterSection->second.end();iterKey++)
- {
- strWrite+=iterKey->first;
- strWrite+=TEXT("=");
- strWrite+=iterKey->second;
- strWrite+=TEXT("/r/n");
- }
- }
- //Writetothefile
- HANDLEhFile=CreateFile(m_strFilePath.c_str(),GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
- if(INVALID_HANDLE_VALUE!=hFile)
- {
- std::vector<BYTE>vtWrite;
- vtWrite.reserve(sizeof(TCHAR)*strWrite.size());
- #ifdefUNICODE
- vtWrite.push_back(0xFF);
- vtWrite.push_back(0xFE);
- for(TSTRING::iteratoriter=strWrite.begin();iter!=strWrite.end();iter++)
- {
- vtWrite.push_back(static_cast<BYTE>(*iter));
- vtWrite.push_back((*iter)>>8);
- }
- #else
- vtWrite.assign(strWrite.begin(),strWrite.end());
- #endif
- DWORDdwWrite=0;
- WriteFile(hFile,&vtWrite[0],vtWrite.size(),&dwWrite,NULL);
- CloseHandle(hFile);
- returnTRUE;
- }
- else
- {
- returnFALSE;
- }
- }
具体使用如下:
- intWINAPIWinMain(HINSTANCEhInstance,
- HINSTANCEhPrevInstance,
- LPTSTRlpCmdLine,
- intnCmdShow)
- {
- //声明一个对象
- CIniParseiniParse;
- //打开相应的ini文件
- iniParse.Open(TEXT("//NAND//test.ini"));
- TSTRINGstrValue;
- intiValue=0;
- //获取特定的SECTION和KEY的数值。可以有两种返回形式,一种是TSTRING,另一种是int。
- strValue=iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO"));
- iValue=iniParse.GetPrivateProfileInt(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO"));
- //更改相应KEY的数值
- iniParse.SetPrivateProfileString(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO"),TEXT("5600"));
- strValue=iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO"));
- //增加新的SECTION和KEY数值
- iniParse.SetPrivateProfileString(TEXT("VERSION_INI_FILE_NEW"),TEXT("VERSION_CONFIG_INFO_NEW"),TEXT("98600"));
- strValue=iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE_NEW"),TEXT("VERSION_CONFIG_INFO_NEW"));
- //写到文件中
- iniParse.Flush();
- return0;
- }
在这里还有一点需要注意的是,因为从效率考虑,SetPrivateProfileString函数更改的数值都只是在内存中做修改,如果需要保存到文件中,需要调用Flush函数。调用Flush函数后,内存的数据就保存到之前Open传入的文件路径中。
如果想保存到C++动态数组中,也可以实现,只是有点麻烦:
- strValue=iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE_NEW"),TEXT("VERSION_CONFIG_INFO_NEW"));
- TCHAR*pNewBuf=newTCHAR[strValue.size()+1];
- _tcscpy(pNewBuf,strValue.c_str());
- delete[]pNewBuf;
用动态数组还需要手动释放资源,相对来说,就不如直接用STL来得更为简便。