ini文件的操作

来源:互联网 发布:西部数码已备案域名 编辑:程序博客网 时间:2024/05/17 20:28
 

轻松实现一个操作ini文件的类

前言:

相信很多朋友编写自己的程序中,都需要把一些数据先期导入到程序中进行初始化。那么这个时候,比较好的做法就是把你所有的数据写入一个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");

}

原创粉丝点击