Wince读取ini的CIniParse类

 

 //========================================================================
//TITLE:
//    Wince读取ini的CIniParse类
//AUTHOR:
//    norains
//DATE:
//    Monday 22-December-2008
//Environment:
//    WINCE5.0 + VS2005 + ARM BSP
//========================================================================   
   
    挺奇怪的是,微软在wince中没有像桌面系统般有读取ini的特定函数。为了解决该问题,网上有不少牛人都给给出了相应的解决方案,比如说:
   
    benkaoya的直接C++/C代码读写:http://blog.csdn.net/benkaoya/archive/2008/01/28/2070648.aspx
   
    xumercury的将以上函数封装为类:http://blog.csdn.net/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的完整代码:
   
    头文件:

  1. //Class Name
  2. // CIniParse
  3. //
  4. //Version:
  5. // 1.0.0
  6. //
  7. //Date:
  8. // 2008.12.22
  9. //
  10. //Author:
  11. // norains
  12. //
  13. #pragma once
  14. #include "windows.h"
  15. #include <string>
  16. #include <vector>
  17. #include <map>
  18. #ifdef UNICODE
  19.  #ifndef TSTRING
  20.   #define TSTRING std::wstring
  21.  #endif
  22. #else
  23.  #ifndef TSTRING
  24.   #define TSTRING std::string
  25.  #endif
  26. #endif
  27. class CIniParse
  28. {
  29. public:
  30.  //-------------------------------------------------------------------------------
  31.  //Description:
  32.  // Open the ini file.
  33.  //-------------------------------------------------------------------------------
  34.  BOOL Open(TSTRING strFile);
  35.  //-------------------------------------------------------------------------------
  36.  //Description:
  37.  // Get the profile value as string type
  38.  //-------------------------------------------------------------------------------
  39.  TSTRING GetPrivateProfileString(const TSTRING &strSection,const TSTRING &strKey);
  40.  //-------------------------------------------------------------------------------
  41.  //Description:
  42.  // Get the profile value as int type
  43.  //-------------------------------------------------------------------------------
  44.  int GetPrivateProfileInt(const TSTRING &strSection,const TSTRING &strKey);
  45.  //-------------------------------------------------------------------------------
  46.  //Description:
  47.  // Set the profile value as string type.The function wouldn't save the data to file
  48.  //but memory. If you want to save to the file, you must call Flush function
  49.  //-------------------------------------------------------------------------------
  50.  BOOL SetPrivateProfileString(const TSTRING &strSection,const TSTRING &strKey,TSTRING strSet);
  51.  //-------------------------------------------------------------------------------
  52.  //Description:
  53.  // Set the profile value as int type.The function wouldn't save the data to file
  54.  //but memory. If you want to save to the file, you must call Flush function
  55.  //-------------------------------------------------------------------------------
  56.  BOOL SetPrivateProfileInt(const TSTRING &strSection,const TSTRING &strKey,int iSet);
  57.  //-------------------------------------------------------------------------------
  58.  //Description:
  59.  // Flush the memory buffer to the file
  60.  //-------------------------------------------------------------------------------
  61.  BOOL Flush();
  62. public:
  63.  CIniParse();
  64.  virtual ~CIniParse();
  65. private:
  66.  //-------------------------------------------------------------------------------
  67.  //Description:
  68.  // Get the line value base on the current offset. After calling, the offset value
  69.  //would move to the head of next line
  70.  //-------------------------------------------------------------------------------
  71.  TSTRING GetLine();
  72.  //-------------------------------------------------------------------------------
  73.  //Description:
  74.  // Check the string value of one line whether is comment or not
  75.  //-------------------------------------------------------------------------------
  76.  static BOOL IsCommentLine(const TSTRING & strLine);
  77.  //-------------------------------------------------------------------------------
  78.  //Description:
  79.  // Check the string value of one line whether is the section.
  80.  //Parameters:
  81.  // strLine : [in] The string value buffer.
  82.  //-------------------------------------------------------------------------------
  83.  static BOOL IsSectionLine(const TSTRING & strLine);
  84.  //-------------------------------------------------------------------------------
  85.  //Description:
  86.  // Get the key value from one line
  87.  //Parameters:
  88.  // strLine : [in] The buffer to find
  89.  //-------------------------------------------------------------------------------
  90.  static TSTRING GetKeyValueFromLine(const TSTRING & strLine);
  91.  //-------------------------------------------------------------------------------
  92.  //Description:
  93.  // Get the key name from one line
  94.  //Parameters:
  95.  // strLine : [in] The buffer to find
  96.  //-------------------------------------------------------------------------------
  97.  static TSTRING GetKeyNameFromLine(const TSTRING & strLine);
  98.  //-------------------------------------------------------------------------------
  99.  //Description:
  100.  // Get the section name from one line
  101.  //Parameters:
  102.  // strLine : [in] The buffer to find
  103.  //-------------------------------------------------------------------------------
  104.  static TSTRING GetSectionNameFromLine(const TSTRING & strLine);
  105.  //-------------------------------------------------------------------------------
  106.  //Description:
  107.  // Remove the space from the string
  108.  //Parameters:
  109.  // strBuf : [in] The buffer to remove
  110.  //Return Value:
  111.  // Return the string without space
  112.  //-------------------------------------------------------------------------------
  113.  static TSTRING RemoveSpace(const TSTRING &strBuf);
  114.  //-------------------------------------------------------------------------------
  115.  //Description:
  116.  // Parse the ini file
  117.  //-------------------------------------------------------------------------------
  118.  void Parse(const TSTRING &strBuf);
  119.  //-------------------------------------------------------------------------------
  120.  //Description:
  121.  // Convert the string to  lowercase
  122.  //-------------------------------------------------------------------------------
  123.  static TSTRING ConvertToLowercase(const TSTRING &strBuf);
  124.  //-------------------------------------------------------------------------------
  125.  //Description:
  126.  // Reset the offset point to the begin
  127.  //-------------------------------------------------------------------------------
  128.  BOOL ResetOffset();
  129.  //-------------------------------------------------------------------------------
  130.  //Description:
  131.  // Check whether the offset arrived the end of the buffer.
  132.  //-------------------------------------------------------------------------------
  133.  BOOL IsOffsetEnd();
  134. private:
  135.  TSTRING m_strFileBuf;
  136.  TSTRING::size_type m_stOffset;
  137.  TSTRING m_strFilePath;
  138.  std::map<TSTRING, std::map<TSTRING,TSTRING> > m_mpValue; //The first TSTRING is section name, the second is key name and last is the value.
  139. };
  140.     

   

 

实现体:
 

  1.    #include "IniParse.h"
  2. #include <deque>
  3. #include <algorithm>
  4. CIniParse::CIniParse():
  5. m_stOffset(0)
  6. {}
  7. CIniParse::~CIniParse()
  8. {}
  9. BOOL CIniParse::Open(TSTRING strFile)
  10. {
  11.  HANDLE hFile = CreateFile(strFile.c_str(),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  12.  if(hFile == INVALID_HANDLE_VALUE)
  13.  {
  14.   return FALSE;
  15.  }
  16.  m_strFilePath = strFile;
  17.  DWORD dwSize = GetFileSize(hFile,NULL);
  18.  //Read the file to buffer
  19.  std::vector<BYTE> vtBuf(dwSize,0);
  20.  DWORD dwRead = 0;
  21.  ReadFile(hFile,&vtBuf[0],vtBuf.size(),&dwRead,NULL);
  22.  vtBuf.resize(dwRead);
  23.  CloseHandle(hFile);
  24.  #ifdef UNICODE
  25.   m_strFileBuf.clear();
  26.   if(vtBuf.size() >= 2)
  27.   {
  28.    if(vtBuf[0] == 0xFF && vtBuf[1] == 0xFE)
  29.    {
  30.     //Unicode file
  31.     //Convert the read buffer to the unicode.The TCHAR here is equal to wchar_t
  32.     std::deque<TCHAR> dqBuf;
  33.     for(std::vector<BYTE>::size_type i = 2; i < vtBuf.size(); i += 2)
  34.     {
  35.      dqBuf.push_back(vtBuf[i] + (vtBuf[i+1] << 8));
  36.     }
  37.     
  38.     m_strFileBuf.insert(m_strFileBuf.end(),dqBuf.begin(),dqBuf.end());
  39.    }
  40.    else
  41.    {
  42.     std::vector<TCHAR> vtBufT;
  43.     vtBufT.resize(MultiByteToWideChar (CP_ACP, 0, reinterpret_cast<char *>(&vtBuf[0]), vtBuf.size(), NULL, 0));
  44.     MultiByteToWideChar (CP_ACP, 0, reinterpret_cast<char *>(&vtBuf[0]), vtBuf.size(), &vtBufT[0], vtBufT.size());  
  45.    
  46.     m_strFileBuf.insert(m_strFileBuf.end(),vtBufT.begin(),vtBufT.end());
  47.    }
  48.   }
  49.  #else
  50.   #error "Unfortunately! The source code donesn't complete in the ASCII environment"
  51.  #endif
  52.  Parse(m_strFileBuf);
  53.  return TRUE;
  54. }
  55. TSTRING CIniParse::GetLine()
  56. {
  57.  TSTRING strReturn;
  58.  if(m_stOffset >= m_strFileBuf.size())
  59.  {
  60.   return TSTRING();
  61.  }
  62.  TSTRING::size_type stPos = m_strFileBuf.find(TEXT("/r/n"),m_stOffset);
  63.  if(stPos == TSTRING::npos)
  64.  {
  65.   strReturn.insert(0,m_strFileBuf,m_stOffset,m_strFileBuf.size() - m_stOffset + 1); 
  66.   //Move the offset position to end of the file
  67.   m_stOffset = m_strFileBuf.size() + 1;
  68.  }
  69.  else
  70.  {
  71.   strReturn.insert(0,m_strFileBuf,m_stOffset,stPos - m_stOffset); 
  72.   //Move the offset position to the back of the "/r/n" 
  73.   m_stOffset = stPos + 2;
  74.  }
  75.  return strReturn;
  76. }
  77. BOOL CIniParse::IsCommentLine(const TSTRING &strLine)
  78. {
  79.  if(strLine.empty() != FALSE || strLine[0] == ';')
  80.  {
  81.   return TRUE;
  82.  }
  83.  else
  84.  {
  85.   return FALSE;
  86.  }
  87. }
  88. BOOL CIniParse::IsSectionLine(const TSTRING &strLine)
  89. {
  90.  TSTRING::size_type stLeft = strLine.find(TEXT("["));
  91.  TSTRING::size_type stRight = strLine.find(TEXT("]"));
  92.  if(strLine.empty() == FALSE && stLeft != TSTRING::npos && stRight != TSTRING::npos && stRight > stLeft)
  93.  {
  94.   return TRUE;
  95.  }
  96.  else
  97.  {
  98.   return FALSE;
  99.  }
  100. }
  101. TSTRING CIniParse::GetKeyValueFromLine(const TSTRING &strLine)
  102. {
  103.  TSTRING::size_type stPosEqual = strLine.find(TEXT("="));
  104.  if(stPosEqual == TSTRING::npos)
  105.  {
  106.   return TSTRING();
  107.  }
  108.  TSTRING strReturn;
  109.  TSTRING::size_type stPosQuoteLeft = strLine.find(TEXT("/""),stPosEqual);
  110.  if(stPosQuoteLeft != TSTRING::npos)
  111.  {
  112.   TSTRING::size_type stPosQuoteRight = strLine.find(TEXT("/""),stPosQuoteLeft + 1);
  113.   if(stPosQuoteRight != TSTRING::npos && stPosQuoteLeft + 1 != stPosQuoteRight)
  114.   {
  115.    strReturn.insert(0,strLine,stPosQuoteLeft + 1,stPosQuoteRight - stPosQuoteLeft - 1);
  116.    return strReturn;
  117.   }
  118.  }
  119.  //Store the string to the buffer
  120.  if(stPosEqual + 1 > strLine.size())
  121.  {
  122.   return TSTRING();
  123.  }
  124.  TSTRING strBuf(strLine,stPosEqual + 1,strLine.size() - stPosEqual);;
  125.  return RemoveSpace(strBuf);
  126. }
  127. TSTRING CIniParse::GetKeyNameFromLine(const TSTRING &strLine)
  128. {
  129.  TSTRING::size_type stPosEqual = strLine.find(TEXT("="));
  130.  if(stPosEqual == 0)
  131.  {
  132.   return TSTRING();
  133.  }
  134.  TSTRING strBuf;
  135.  if(stPosEqual == TSTRING::npos)
  136.  {
  137.   //All of the string line is the key name
  138.   strBuf = strLine;
  139.  }
  140.  else
  141.  {
  142.   strBuf.clear();
  143.   strBuf.insert(0,strLine,0,stPosEqual);
  144.  }
  145.  return RemoveSpace(strBuf);
  146. }
  147. TSTRING CIniParse::GetSectionNameFromLine(const TSTRING &strLine)
  148. {
  149.  TSTRING::size_type stLeft = strLine.find(TEXT("["));
  150.  TSTRING::size_type stRight = strLine.find(TEXT("]"));
  151.  if(!(strLine.empty() == FALSE && stLeft != TSTRING::npos && stRight != TSTRING::npos && stRight > stLeft))
  152.  {
  153.   return TSTRING();
  154.  }
  155.  TSTRING strBuf(strLine,stLeft + 1,stRight - stLeft - 1); 
  156.  return RemoveSpace(strBuf);
  157. }
  158. TSTRING CIniParse::RemoveSpace(const TSTRING &strBuf)
  159. {
  160.  if(strBuf.find(TEXT(" ")) != TSTRING::npos)
  161.  {
  162.   //Remove the space
  163.   TSTRING strReturn;
  164.   for(TSTRING::size_type stPos = 0; stPos < strBuf.size(); stPos ++)
  165.   {
  166.    if(strBuf[stPos] != ' ')
  167.    {
  168.     strReturn.push_back(strBuf[stPos]);
  169.    }
  170.   }
  171.   return strReturn;
  172.  }
  173.  else
  174.  {
  175.   //No space
  176.   return strBuf;
  177.  }
  178. }
  179. void CIniParse::Parse(const TSTRING &strBuf)
  180. {
  181.  //Reset the file pointer to the begin
  182.  ResetOffset();
  183.  std::map<TSTRING,TSTRING> mpKey;
  184.  TSTRING strSection;
  185.  while(TRUE)
  186.  {
  187.   TSTRING strLine = GetLine();
  188.   if(strLine.empty() != FALSE || IsCommentLine(strLine) != FALSE)
  189.   {
  190.    if(IsOffsetEnd())
  191.    {
  192.     break;
  193.    }
  194.    else
  195.    {
  196.     continue;
  197.    }
  198.   }
  199.   if(IsSectionLine(strLine) != FALSE)
  200.   {   
  201.    if(strSection.empty() != FALSE)
  202.    {
  203.     //It's the first section
  204.     strSection = GetSectionNameFromLine(strLine);
  205.     continue;
  206.    }
  207.    //Store the last section value
  208.    m_mpValue.insert(std::make_pair(strSection,mpKey));
  209.    strSection = GetSectionNameFromLine(strLine);
  210.    mpKey.clear();
  211.   }
  212.   else
  213.   {
  214.    if(strSection.empty() != FALSE)
  215.    {
  216.     //The section name is empty, so needn't store the key value
  217.     continue;
  218.    }
  219.    //Store the key value and name
  220.    TSTRING strKeyName = GetKeyNameFromLine(strLine);
  221.    if(strKeyName.empty() == FALSE)
  222.    {
  223.     mpKey.insert(std::make_pair(strKeyName,GetKeyValueFromLine(strLine)));
  224.    }
  225.   }
  226.  }
  227.  //Store the last section value
  228.  if(strSection.empty() == FALSE)
  229.  {
  230.   m_mpValue.insert(std::make_pair(strSection,mpKey));
  231.  }
  232. }
  233. TSTRING CIniParse::ConvertToLowercase(const TSTRING &strBuf)
  234. {
  235.  std::vector<TCHAR> vtBuf(strBuf.length() + 1,0);
  236.  _tcscpy(&vtBuf[0],strBuf.c_str());
  237.  return _tcslwr(&vtBuf[0]);
  238. }
  239. BOOL CIniParse::ResetOffset()
  240. {
  241.  m_stOffset = 0;
  242.  return TRUE;
  243. }
  244. BOOL CIniParse::IsOffsetEnd()
  245. {
  246.  if(m_stOffset >= m_strFileBuf.size())
  247.  {
  248.   return TRUE;
  249.  }
  250.  else
  251.  {
  252.   return FALSE;
  253.  }
  254. }
  255. TSTRING CIniParse::GetPrivateProfileString(const TSTRING &strSection,const TSTRING &strKey)
  256. {
  257.  if(m_mpValue.empty() != FALSE)
  258.  {
  259.   return TSTRING();
  260.  }
  261.  //Ignoring the character case to find the specified key 
  262.  for(std::map<TSTRING, std::map<TSTRING,TSTRING>>::iterator iterSection = m_mpValue.begin(); iterSection != m_mpValue.end(); iterSection ++)
  263.  {
  264.   if(ConvertToLowercase(iterSection->first) == ConvertToLowercase(strSection))
  265.   {
  266.    for(std::map<TSTRING,TSTRING>::iterator iterKey = iterSection->second.begin(); iterKey != iterSection->second.end(); iterKey ++)
  267.    {
  268.     if(ConvertToLowercase(iterKey->first) == ConvertToLowercase(strKey))
  269.     {
  270.      return iterKey->second;
  271.     }
  272.    }
  273.   }
  274.  }
  275.  return TSTRING();
  276. }
  277. int CIniParse::GetPrivateProfileInt(const TSTRING &strSection,const TSTRING &strKey)
  278. {
  279.  return _ttoi(GetPrivateProfileString(strSection,strKey).c_str());
  280. }
  281. BOOL CIniParse::SetPrivateProfileString(const TSTRING &strSection,const TSTRING &strKey,TSTRING strSet)
  282. {
  283.  //Ignoring the character case to find the specified key 
  284.  for(std::map<TSTRING, std::map<TSTRING,TSTRING>>::iterator iterSection = m_mpValue.begin(); iterSection != m_mpValue.end(); iterSection ++)
  285.  {
  286.   if(ConvertToLowercase(iterSection->first) == ConvertToLowercase(strSection))
  287.   {
  288.    for(std::map<TSTRING,TSTRING>::iterator iterKey = iterSection->second.begin(); iterKey != iterSection->second.end(); iterKey ++)
  289.    {
  290.     if(ConvertToLowercase(iterKey->first) == ConvertToLowercase(strKey))
  291.     {
  292.      iterKey->second = strSet;
  293.      return TRUE;
  294.     }
  295.    }
  296.    //Add the new key value
  297.    iterSection->second.insert(std::make_pair(strKey,strSet));
  298.    return TRUE;
  299.   }
  300.  }
  301.  //Add the new section and key value
  302.  std::map<TSTRING,TSTRING> mpKey;
  303.  mpKey.insert(std::make_pair(strKey,strSet));
  304.  m_mpValue.insert(std::make_pair(strSection,mpKey));
  305.  return TRUE;
  306. }
  307. BOOL CIniParse::SetPrivateProfileInt(const TSTRING &strSection,const TSTRING &strKey,int iSet)
  308. {
  309.  std::vector<TCHAR> vtBuf(MAX_PATH,0);
  310.  TSTRING strSet = _itot(iSet,&vtBuf[0],10);
  311.  return SetPrivateProfileString(strSection,strKey,strSet);
  312. }
  313. BOOL CIniParse::Flush()
  314. {
  315.  TSTRING strWrite;
  316.  //strWrite.reserve(m_mpValue.size());
  317.  //Store the string value to the buffer
  318.  for(std::map<TSTRING, std::map<TSTRING,TSTRING>>::iterator iterSection = m_mpValue.begin(); iterSection != m_mpValue.end(); iterSection ++)
  319.  {
  320.   strWrite += TEXT("/r/n[");
  321.   strWrite += iterSection->first;
  322.   strWrite += TEXT("]/r/n");
  323.   for(std::map<TSTRING,TSTRING>::iterator iterKey = iterSection->second.begin(); iterKey != iterSection->second.end(); iterKey ++)
  324.   {
  325.    strWrite += iterKey->first;
  326.    strWrite += TEXT("=");
  327.    strWrite += iterKey->second;
  328.    strWrite += TEXT("/r/n");
  329.   }
  330.  }
  331.  //Write to the file
  332.  HANDLE hFile = CreateFile(m_strFilePath.c_str(),GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
  333.  if(INVALID_HANDLE_VALUE != hFile)
  334.  {
  335.   std::vector<BYTE> vtWrite;
  336.   vtWrite.reserve(sizeof(TCHAR) * strWrite.size());
  337.     
  338.   #ifdef UNICODE
  339.    vtWrite.push_back(0xFF);
  340.    vtWrite.push_back(0xFE);
  341.    for(TSTRING::iterator iter = strWrite.begin(); iter != strWrite.end(); iter++)
  342.    {
  343.     vtWrite.push_back(static_cast<BYTE>(*iter));
  344.     vtWrite.push_back((*iter)>>8);
  345.    }
  346.   #else
  347.    vtWrite.assign(strWrite.begin(),strWrite.end());
  348.   #endif
  349.   DWORD dwWrite = 0;
  350.   WriteFile(hFile,&vtWrite[0],vtWrite.size(),&dwWrite,NULL);
  351.   CloseHandle(hFile);
  352.   return TRUE;
  353.  }
  354.  else
  355.  {
  356.   return FALSE;
  357.  } 
  358. }
  359.     

具体使用如下:
 

  1.    int WINAPI WinMain( HINSTANCE hInstance,
  2.      HINSTANCE hPrevInstance,
  3.      LPTSTR    lpCmdLine,
  4.      int       nCmdShow)
  5. {
  6.  //声明一个对象
  7.  CIniParse iniParse;
  8.  //打开相应的ini文件
  9.  iniParse.Open(TEXT("//NAND//test.ini"));
  10.  TSTRING strValue ;
  11.  int iValue = 0;
  12.  //获取特定的SECTION和KEY的数值。可以有两种返回形式,一种是TSTRING,另一种是int。
  13.  strValue = iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO")); 
  14.  iValue = iniParse.GetPrivateProfileInt(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO"));
  15.  //更改相应KEY的数值
  16.  iniParse.SetPrivateProfileString(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO"),TEXT("5600")); 
  17.  strValue = iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE"),TEXT("VERSION_CONFIG_INFO")); 
  18.  //增加新的SECTION和KEY数值
  19.  iniParse.SetPrivateProfileString(TEXT("VERSION_INI_FILE_NEW"),TEXT("VERSION_CONFIG_INFO_NEW"),TEXT("98600")); 
  20.  strValue = iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE_NEW"),TEXT("VERSION_CONFIG_INFO_NEW")); 
  21.  //写到文件中
  22.  iniParse.Flush();
  23.  return 0; 
  24. }

    在这里还有一点需要注意的是,因为从效率考虑,SetPrivateProfileString函数更改的数值都只是在内存中做修改,如果需要保存到文件中,需要调用Flush函数。调用Flush函数后,内存的数据就保存到之前Open传入的文件路径中。
   
    如果想保存到C++动态数组中,也可以实现,只是有点麻烦:
    

  1.   strValue = iniParse.GetPrivateProfileString(TEXT("VERSION_INI_FILE_NEW"),TEXT("VERSION_CONFIG_INFO_NEW"));  
  2.  TCHAR *pNewBuf = new TCHAR[strValue.size() + 1];
  3.  _tcscpy(pNewBuf,strValue.c_str());
  4.  delete []pNewBuf;

 用动态数组还需要手动释放资源,相对来说,就不如直接用STL来得更为简便。

纯c读写ini配置文件 用c/c++读写ini配置文件有不少第三方的开源库,如iniparser、libini、rwini、UltraLightINIParser等,但都不理想,往往代码较大、功能较弱、 接口使用不方便。尤其在大小写处理、前后空格、各种注释、跨平台换行符支持、带引号字符串处理、无section操作、原格式保持等方面存在问题。 现将本人精心制作的ini读写程序源码奉献给大家,纯c编写,简洁好用。支持windows和linux。 主要特点: 1、支持;和#注释符号,支持行尾注释。 2、支持带引号'或"成对匹配的字符串,提取时自动去引号。引号中可带其它引号或;#注释符。 3、支持无section或空section(名称为空)。 4、支持10、16、8进制数,0x开头为16进制数,0开头为8进制。 5、支持section、key或=号前后带空格。 6、支持\n、\r、\r\n或\n\r换行格式。 7、不区分section、key大小写,但写入时以新串为准,并保持其大小写。 8、新增数据时,若section存在则在该节最后一个有效数据后添加,否则在文件尾部添加。 9、支持指定key所在整行删除,即删除该键值,包括注释。 10、可自动跳过格式错误行,修改时仍然保留。 11、修改时保留原注释:包括整行注释、行尾注释(包括前面空格)。 12、修改时保留原空行。以上三点主要是尽量保留原格式。 不足之处: 1、不支持单key多value(逗号分割),只能一次性提取后自行处理。 2、不支持同名重复section和key。(重复section可视为错误,重复key则可能造成分歧) 3、不能提取所有section或key名称。 使用只需两个文件inirw.h、inirw.c,另有测试程序和工程文件,支持windows和linux。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值