惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google DeepMind News
Google DeepMind News
T
Tenable Blog
博客园_首页
S
Securelist
Spread Privacy
Spread Privacy
Google Online Security Blog
Google Online Security Blog
Forbes - Security
Forbes - Security
Engineering at Meta
Engineering at Meta
U
Unit 42
L
LINUX DO - 热门话题
量子位
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
C
Cyber Attacks, Cyber Crime and Cyber Security
K
Kaspersky official blog
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
The Last Watchdog
The Last Watchdog
Google DeepMind News
Google DeepMind News
GbyAI
GbyAI
Martin Fowler
Martin Fowler
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Security Latest
Security Latest
Scott Helme
Scott Helme
V
Vulnerabilities – Threatpost
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
Know Your Adversary
Know Your Adversary
Cisco Talos Blog
Cisco Talos Blog
The Register - Security
The Register - Security
T
The Blog of Author Tim Ferriss
aimingoo的专栏
aimingoo的专栏
V2EX - 技术
V2EX - 技术
T
Tailwind CSS Blog
月光博客
月光博客
Recent Announcements
Recent Announcements
G
Google Developers Blog
F
Full Disclosure
W
WeLiveSecurity
宝玉的分享
宝玉的分享
腾讯CDC
G
GRAHAM CLULEY
Vercel News
Vercel News
Simon Willison's Weblog
Simon Willison's Weblog
美团技术团队
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Help Net Security
Help Net Security

博客园 - hzman

ASP采集入库生成本地文件的几个FUCTION 用XMLhttp编写web采集程序 无需安装软件架设NOD32升级服务器指南! 架设NOD32升级服务器 - hzman - 博客园 C#游戏外挂代码 VC7转换到VC8的常见问题 OllyDBG 入门系列(二)-字串参考 OllyDBG 入门系列(一)-认识OllyDBG - hzman - 博客园 live.cn邮箱注册帐号方法 - hzman - 博客园 免手机验证码网站备案 ASP同一虚拟空间放多个站点(各站点对应独立域名)的方法 QQ空间代码说明 页面间传值方法 C#代码,功能为拦截http请求,并篡改其中任何内容 C#编写NotifyIcon 深入浅出之正则表达式 两个分析HTML网页的方法 提取HTML代码中文字的C#函数 c#字符串截取函数
ini文件操作类
hzman · 2007-10-11 · via 博客园 - hzman

[转载]  
前言:

    相信很多朋友在编写自己的程序中,都需要把一些数据先期导入到程序中进行初始化。那么这个时候,比较好的做法就是把你所有的数据写入一个ini文件,然后在程序去读ini文件中的数据对行初始化。

一.INI简介
       那么什么是ini文件呢?ini文件是Initialization file的缩写,意即初始化文件。(从名字就可以看出它的功能了吧)。不仅你自己的程序可以使用ini文件,其实windows操作系统也有自己的ini文件---win.ini,保存在%WinDir%\system32目录下。Windows通过该文件对当前操作系统进行配置。

    ini文件里的数据的存取是采取的是预先约定好的 “项-值”存储结构,各种数据被分门别类的存储。以下是win.ini 文件的部分内容。

[Mail]

MAPI=1

CMC=1

CMCDLLNAME=mapi.dll

CMCDLLNAME32=mapi32.dll

MAPIX=1

MAPIXVER=1.0.0.1

OLEMessaging=1
 
                    表1

通过以上内容,我们可以看到,ini文件将各种数据分成很多以“[ ]”组成的节,而在每一个“节”中又包含了很多“项”,“项”后面紧跟着一个等号,等号后面则是该项的值。在该例中[Mail]就是一个“节”,MAPI是一个项,1则是MAPI的值。
    所以,它的通用形式我们可以总结成:

[Section]

Key=KeyValue

二.操作ini文件的API
windows SDK提供有两组API对ini文件进行读写。


 写
 
GetPrivateProfileString

GetPrivateProfileInt
 WritePrivateProfileString
 
GetPrivateProfileSection
 WritePrivateProfileSection
 
GetPrivateProfileSectionNames
  
 
GetPrivateProfileStruct
 WritePrivateProfileStruct

                                                                             表2


 写
 
GetProfileString

GetProfileInt
 WriteProfileString
 
GetProfileSection
 WritePrivateProfileSection

                                                                             表3

    对用户的配置文件来说,一般我们使用的是表2中的函数,这一点从函数中的“private”就可以看出它是针对私有的配置文件的函数(又是废话!)。而表3中的函数则是提供给针对系统配置文件,即win.ini进行操作的函数。现只准备介绍表2中的函数,这也是使用率最高的,表3中的函数操作和表2中的函数操作类同,故略。

       
    现在我们来看看这几个函数的功能:

DWORD GetPrivateProfileString(

  LPCTSTR lpAppName,           //节名,即Section

  LPCTSTR lpKeyName,           //项名,即Key

  LPCTSTR lpDefault,                //缺省返回字符串。如lpKeyName未找到,拷贝lpDefault到lpReturnedString

  LPTSTR lpReturnedString,       //返回字符串的缓冲地址

  DWORD nSize,                       //缓冲大小

  LPCTSTR lpFileName             //ini文件路径

);

功能:根据指定的Section和 Key得到KeyValue,存放在lpReturnedString中

返回:返回拷贝到缓冲中的字符个数。不包括结束符

UINT GetPrivateProfileInt(

  LPCTSTR lpAppName,           //节名,即Section
  LPCTSTR lpKeyName,           //项名,即Key

  INT nDefault,                           //缺省返回整型值。如lpKeyName未找到,函数返回nDefault的值

  LPCTSTR lpFileName             //ini文件路径

);

功能:根据指定的Section和 Key得到整型KeyValue

返回:返回得到的整型KeyValue

BOOL WritePrivateProfileString(

  LPCTSTR lpAppName,           //节名,即Section
  LPCTSTR lpKeyName,           //项名,即Key

  LPCTSTR lpString,                  //要写入的字符串

  LPCTSTR lpFileName             //ini文件路径
);

功能:向指定的Section和 Key写入KeyValue。
      如果lpString为NULL,则删除当前lpKeyName

    如果lpKeyName=lpString=NULL,则删除当前Section以及其下的所有Key

       如果Section或者Key不存在,则创建;存在则覆盖

返回:写入成功。

DWORD GetPrivateProfileSectionNames(

  LPTSTR lpszReturnBuffer,             //存放所有Section的缓冲地址

  DWORD nSize,                             //缓冲大小

  LPCTSTR lpFileName                   //ini文件路径

);

功能:得到ini文件中所有Section名。

返回:返回拷贝到缓冲中的字符个数。不包括结束符。
注意:返回的所有Section在缓冲中的存放格式为“Section1”,0,“Section2”,0。。。。

      若需要得到具体的每个Section,则需要进行字符串解析。在后面的IniFile类中的GetAllKeysAndValues函数中会看到解
      析步骤。

DWORD GetPrivateProfileSection(

  LPCTSTR lpAppName,                   //节名,即Section    

  LPTSTR lpReturnedString,              //存放指定Section下所有的Key和KeyValue的缓冲地址

  DWORD nSize,                              //缓冲大小

  LPCTSTR lpFileName                     //ini文件路径

);

功能:得到指定Section下所有的Key和KeyValue。

返回:返回拷贝到缓冲中的字符个数。不包括结束符。

注意:返回的“项-值对”在缓冲中的存放格式为“Key1=KeyValue1”,0,“Key2=KeyValue2”,0 。。。。

若需要得到具体的Key和KeyValue,则需要进行字符串解析。在后面的IniFile类中的GetAllKeysAndValues函数中会看到解析步骤。

GetPrivateProfileStruct和WritePrivateProfileStruct用的较少,本文也未介绍,感兴趣的朋友可以自己看看MSDN,里面也有详细介绍。

三.一个ini的类
    有了以上的API后,我们就可以轻松的制作一个简单的操作ini文件的类了。

//////////////////////////////////////////////////////////////////////////

// File: IniFile.h

// Date: October 2004

// Author: lixiaosan

// Email: airforcetwo@163.com

// Copyright (c) 2004. All Rights Reserved.

//////////////////////////////////////////////////////////////////////////

#if !defined(AFX_INIFILE_H__B5C0D7F7_8353_4C93_AAA4_38A688CA253C__INCLUDED_)

#define AFX_INIFILE_H__B5C0D7F7_8353_4C93_AAA4_38A688CA253C__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

class CIniFile  

{

public:

         CIniFile();

         virtual ~CIniFile();

         //    设置ini文件路径
    //    成功返回TRUE;否则返回FALSE

         BOOL         SetPath(CString strPath);

         //    检查section是否存在
    //    存在返回TRUE;否则返回FALSE

         BOOL         SectionExist(CString strSection);

         //    从指定的Section和Key读取KeyValue
        //    返回KeyValue

         CString         GetKeyValue(CString    strSection,

                                                        CString    strKey);         

         //    设置Section、Key以及KeyValue,若Section或者Key不存在则创建

         void          SetKeyValue(CString    strSection, 

                                                   CString    strKey, 

                                                   CString    strKeyValue);

         //    删除指定Section下的一个Key

         void          DeleteKey(CString strSection,

                                               CString strKey);

         //    删除指定的Section以及其下的所有Key

         void          DeleteSection(CString strSection);

         //    获得所有的Section
        //    返回Section数目

         int              GetAllSections(CStringArray& strArrSection);

         //    根据指定Section得到其下的所有Key和KeyValue
        //    返回Key的数目

         int              GetAllKeysAndValues(CString strSection,

                                                                     CStringArray& strArrKey,

                                                                     CStringArray& strArrKeyValue);

         //       删除所有Section

         void          DeleteAllSections();

private:

         //       ini文件路径

         CString m_strPath;

};

#endif // !defined(AFX_INIFILE_H__B5C0D7F7_8353_4C93_AAA4_38A688CA253C__INCLUDED_)

//////////////////////////////////////////////////////////////////////////

// File: IniFile.cpp

// Date: October 2004

// Author: lixiaosan

// Email: airforcetwo@163.com

// Copyright (c) 2004. All Rights Reserved.

//////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

//#include "test6.h"

#include "IniFile.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

#define         MAX_SECTION                260        //Section最大长度

#define         MAX_KEY                         260        //KeyValues最大长度

#define         MAX_ALLSECTIONS     65535    //所有Section的最大长度

#define         MAX_ALLKEYS              65535    //所有KeyValue的最大长度

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CIniFile::CIniFile()

{

}

CIniFile::~CIniFile()

{

}

//////////////////////////////////////////////////////////////////////////

//   Public Functions

//////////////////////////////////////////////////////////////////////////

BOOL CIniFile::SetPath(CString strPath)

{

         m_strPath = strPath;

         //       检查文件是否存在

         DWORD  dwFlag = GetFileAttributes((LPCTSTR)m_strPath);

         //       文件或者路径不存在,返回FALSE

         if( 0xFFFFFFFF == dwFlag )

                   return FALSE;

         //       路径是目录,返回FALSE

         if (  FILE_ATTRIBUTE_DIRECTORY & dwFlag )

                   return FALSE;

         return TRUE;

}

BOOL CIniFile::SectionExist(CString strSection)

{

         TCHAR chSection[MAX_SECTION];

         DWORD dwRetValue;

         dwRetValue = GetPrivateProfileString(

                  (LPCTSTR)strSection,

                   NULL,

                   _T(""),

                  chSection,

                  sizeof(chSection)/sizeof(TCHAR),

                  (LPCTSTR)m_strPath);

         return (dwRetValue>0);

}

CString CIniFile::GetKeyValue(CString strSection, 

                                                         CString strKey)

{

         TCHAR         chKey[MAX_KEY];

         DWORD         dwRetValue;

         CString strKeyValue=_T("");

         dwRetValue = GetPrivateProfileString(

                  (LPCTSTR)strSection,

                  (LPCTSTR)strKey,

                   _T(""),

                   chKey,

                  sizeof(chKey)/sizeof(TCHAR),

                  (LPCTSTR)m_strPath);       

         strKeyValue = chKey;

         return strKeyValue;

}

void CIniFile::SetKeyValue(CString strSection,

                                                 CString strKey,

                                                 CString strKeyValue)

{

         WritePrivateProfileString(

                  (LPCTSTR)strSection, 

                  (LPCTSTR)strKey, 

                  (LPCTSTR)strKeyValue, 

                  (LPCTSTR)m_strPath);

}

void CIniFile::DeleteKey(CString strSection, CString strKey)

{

         WritePrivateProfileString(

                  (LPCTSTR)strSection, 

                  (LPCTSTR)strKey, 

                   NULL,          //       这里写NULL,则删除Key

                  (LPCTSTR)m_strPath);

}

void CIniFile::DeleteSection(CString strSection)

{

         WritePrivateProfileString(

                  (LPCTSTR)strSection, 

                   NULL,          

                   NULL,          //       这里都写NULL,则删除Section

                  (LPCTSTR)m_strPath);

}

int CIniFile::GetAllSections(CStringArray& strArrSection)

{

         int dwRetValue, i, j, iPos=0;

         TCHAR chAllSections[MAX_ALLSECTIONS];

         TCHAR chTempSection[MAX_SECTION];

         ZeroMemory(chAllSections, MAX_ALLSECTIONS);

         ZeroMemory(chTempSection, MAX_SECTION);

         dwRetValue = GetPrivateProfileSectionNames(

                  chAllSections,

                  MAX_ALLSECTIONS,

                  m_strPath);

         //       因为Section在数组中的存放形式为“Section1”,0,“Section2”,0,0。
    //       所以如果检测到连续两个0,则break

         for(i=0; i<MAX_ALLSECTIONS; i++) 

         { 

                  if( chAllSections[i] == NULL ) 

                   {

                            if( chAllSections[i] == chAllSections[i+1] )

                                     break; 

                   }

         } 

         i++; //         保证数据读完

         strArrSection.RemoveAll(); //         清空数组

         for(j=0; j<i; j++) 

         { 

                  chTempSection[iPos++] = chAllSections[j]; 

                  if( chAllSections[j] == NULL ) 

                   {  

                            strArrSection.Add(chTempSection); 

                            ZeroMemory(chTempSection, MAX_SECTION);

                            iPos = 0; 

                   } 

         }

         return strArrSection.GetSize();

}

int CIniFile::GetAllKeysAndValues(CString  strSection, 

                                                            CStringArray&         strArrKey, 

                                                            CStringArray& strArrKeyValue)

{

         int dwRetValue, i, j, iPos=0;

         TCHAR chAllKeysAndValues[MAX_ALLKEYS];

         TCHAR chTempkeyAndValue[MAX_KEY];

         CString strTempKey;

         ZeroMemory(chAllKeysAndValues, MAX_ALLKEYS);

         ZeroMemory(chTempkeyAndValue, MAX_KEY);

         dwRetValue = GetPrivateProfileSection(

                  strSection,

                  chAllKeysAndValues,

                  MAX_ALLKEYS,

                  m_strPath);

         //       因为Section在数组中的存放形式为“Key1=KeyValue1”,0,“Key2=KeyValue2”,0
         //       所以如果检测到连续两个0,则break

         for(i=0; i<MAX_ALLSECTIONS; i++) 

         { 

                  if( chAllKeysAndValues[i] == NULL ) 

                   {

                            if( chAllKeysAndValues[i] == chAllKeysAndValues[i+1] )

                                     break; 

                   }

         } 

         i++;

         strArrKey.RemoveAll();

         strArrKeyValue.RemoveAll();

         for(j=0; j<i; j++) 

         { 

                  chTempkeyAndValue[iPos++] = chAllKeysAndValues[j]; 

                  if( chAllKeysAndValues[j] == NULL ) 

                   {  

                            strTempKey = chTempkeyAndValue; 

                            strArrKey.Add( strTempKey.Left(strTempKey.Find('=')) );

                            strArrKeyValue.Add( strTempKey.Mid(strTempKey.Find('=')+1) );

                            ZeroMemory(chTempkeyAndValue, MAX_KEY);

                            iPos = 0; 

                   } 

         }

         return strArrKey.GetSize();

}

void CIniFile::DeleteAllSections()

{

         int nSecNum; 

         CStringArray strArrSection; 

         nSecNum = GetAllSections(strArrSection); 

         for(int i=0; i<nSecNum; i++) 

         { 

                  WritePrivateProfileString(

                            (LPCTSTR)strArrSection[i],

                            NULL,

                            NULL,

                            (LPCTSTR)m_strPath);       

         }

}

四.例子
比如在存在一个myfile.ini文件,内容如下:

[student]

number=40

male=25

female=15

average_age=15

[computer]

cpu=2.0

motherboard=ASUS

harddisk=120

ram=512

display=sansung

现在把IniFile.h和IniFile.cpp 加入到你的工程中。在使用他的类中#include “IniFile.h”;

         CIniFile file;

         CStringArray arrSection, arrKey, arrkeyValue;

         file.SetPath("f:\\ myfile.ini");

         CString str="";

         if(file.SectionExist("student"))

         {

                  //str="15"

                   str = file.GetKeyValue("student", "female");

                   //设置number为50

                  file.SetKeyValue("student", "number", "50");

                   //因为在student中computer_num不存在,所以增加一项

                  file.SetKeyValue("student", "computer_num", "30");

                   //得到所有section

                   int num = file.GetAllSections(arrSection);

                   str = "";

                   for(int i=0; i<num; i++)

                   {

                            str += arrSection[i] + " ";//str="student computer ";

                   }

                   //得到所有Key和KeyValue

                   int num = file.GetAllKeysAndValues("computer", arrKey, arrkeyValue);

                   str = "";

                   for(int j=0; j<num; j++)

                   {

                            //arrKey保存了computer下所有的Key

                            //arrkeyValue保存了computer下所有的KeyValue

                            str = arrKey[j];

                            str = arrkeyValue[j];

                   }

                   //删除student下的computer_num

                  file.DeleteKey("student", "computer_num");

                   //删除student

                  file.DeleteSection("student");

     }

    有兴趣的朋友,可以在该类基础上进行扩展,添加你自己喜欢的功能。比如说返回int而不是字符串。