Windows中有一种比较特殊的文本文件,就是ini文件,该文件是一种结构化的文本文件,主要用来保存简单的配置信息,比如windows中的win.ini,system.ini等都是这种类型的文件,你可以用记事本等文本编辑器打开它并进行查看修改。
Windows为了很好的读写这类文件,提供了一些专门的读写函数,我们在自己的应用程序中可以充分的利用这些函数来保存一些比较简单的配置信息。
Windows的ini文件结构一般如下:
; 注释部分,以分号开头
[Section1]
key1=name1
key2=name2
;每个节(section)以方括号括起来,每个section下面可以有0到多个key
;以key=value的形式书写,=前面是key的名称,=后面是key的value
[Section2]
key3=value3
key4=value4
从上面可以看出一个ini文件主要有3部分组成,以分号开始的注释,以方括号括起来的节(section)以及在每个节下面的以key=value形式的键,在同一个section下面key的名称必须唯一,在不同的section下面可以相同,在整个ini文件中section的名称不能重复。
ini文件的结构很简单,下面的程序,演示了如何用windows提供的api进行读写.
新建一个VC6++win32的空的工程,添入以下文件:
/*
FileName: ini.c
Function: Read and write ini file
Desc: Windows 32 bits Application
本程序演示了如何读写ini文件,ini文件是一种特殊的文本文件,它的结构如下:
; comment
[Section1]
Key1=value1
Key2=value2
[Section2]
;keys
Key3=value3
Key4=value4
......
*/
#include <windows.h>
#include "resource.h"
HWND hWinMain = NULL; // 主对话框句柄
char szProfileName[MAX_PATH]; // 用来保存ini文件的全路径名称
char szBuffer1[32760]; // 用来保存读取的Sections
char szBuffer2[32760]; // 用来保存读取的Keys
char szFileName[] = TEXT("\\Option.ini"); // ini 文件名称
char szSecPos[] = TEXT("Windows Position");
char szKeyX[] = TEXT("X");
char szKeyY[] = TEXT("Y");
char szFmt1[] = TEXT("%d");
char szFmtSection[] = TEXT("[%s]");
char szCrLf[] = "\r\n"; // 回车换行
void EnumIni(); // 读取ini文件,枚举所有的sections以及keys
void GetPosition(); // 获取对话框的坐标
void SavePosition(); // 保存对话框的坐标
LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
{
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, 0);
return 0;
}
void EnumIni()
{
char szBuffer[256];
char *p, *q;
SetDlgItemText(hWinMain, IDC_INI, NULL);
// 得到所有的sections,每个section都是以0结尾的字符串,最后整个字符串以0结尾
GetPrivateProfileSectionNames(szBuffer1, sizeof(szBuffer1), szProfileName);
p = szBuffer1; // 指向szBuffer1中的第一个Section
while ( p[0] ) // 循环读取section
{
wsprintf(szBuffer, szFmtSection, p);
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)szBuffer);
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)szCrLf);
// 得到该Section下面的所有keys
// 每个key都是以0结尾的字符串,最后整个字符串以0 结尾
GetPrivateProfileSection(p, szBuffer2, sizeof(szBuffer2), szProfileName);
q = szBuffer2; // 指向第一个key
while ( q[0] ) // 循环读取所有的keys
{
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)q);
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)szCrLf);
q += strlen(q) + 1; // 指针移动到下一个key
}
p += strlen(p) + 1; // 指针移动到下一个section
}
}
void GetPosition()
{
int x, y;
// 获取当前的路径
GetCurrentDirectory(MAX_PATH, szProfileName);
// 得到ini文件的全路径
lstrcat(szProfileName, szFileName);
// 得到位置section的坐标值,如果失败,则默认为(50, 50)
x = GetPrivateProfileInt(szSecPos, szKeyX, 50, szProfileName);
y = GetPrivateProfileInt(szSecPos, szKeyY, 50, szProfileName);
// 设置对话框的位置
SetWindowPos(hWinMain, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
}
void SavePosition()
{
char szBuffer[512];
RECT rc;
// 得到窗口的坐标, 并切保存到ini文件
GetWindowRect(hWinMain, &rc);
wsprintf(szBuffer, szFmt1, rc.left);
WritePrivateProfileString(szSecPos, szKeyX, szBuffer, szProfileName);
wsprintf(szBuffer, szFmt1, rc.top);
WritePrivateProfileString(szSecPos, szKeyY, szBuffer, szProfileName);
}
LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char szSection[256];
char szKey[256];
char szValue[256];
char szBuffer[256];
switch ( uMsg )
{
case WM_CLOSE: // 对话框关闭保存对话框的位置
SavePosition();
EndDialog(hWnd, 0);
break;
case WM_INITDIALOG: // 对话框初始化,得到对话框的原来位置,并且读取ini文件
hWinMain = hWnd;
GetPosition();
EnumIni(); // 枚举ini文件的内容
break;
case WM_COMMAND:
GetDlgItemText(hWnd, IDC_SEC, szSection, sizeof(szSection));
GetDlgItemText(hWnd, IDC_KEY, szKey, sizeof(szKey));
GetDlgItemText(hWnd, IDC_VALUE, szValue, sizeof(szValue));
switch ( LOWORD(wParam) )
{
case IDC_SEC:
case IDC_KEY:
case IDC_VALUE:
case IDC_INI:
return TRUE;
case IDC_DEL_SEC: // 删除一个section
WritePrivateProfileString(szSection, NULL, NULL, szProfileName);
break;
case IDC_DEL_KEY: // 删除一个key
WritePrivateProfileString(szSection, szKey, NULL, szProfileName);
break;
case IDC_SET_KEY: // 保存一个key
WritePrivateProfileString(szSection, szKey, szValue, szProfileName);
break;
case IDC_GET_KEY: // 得到一个key
GetPrivateProfileString(szSection, szKey, NULL, szBuffer, sizeof(szBuffer), szProfileName);
SetDlgItemText(hWnd, IDC_VALUE, szBuffer);
break;
default:
break;
}
EnumIni(); // 更新ini文件的显示信息
break;
default:
return FALSE;
}
return TRUE;
}
//resource.h
#define IDD_MAIN 101
#define IDC_SEC 1000
#define IDC_KEY 1001
#define IDC_VALUE 1002
#define IDC_DEL_SEC 1003
#define IDC_DEL_KEY 1004
#define IDC_GET_KEY 1005
#define IDC_SET_KEY 1006
#define IDC_INI 1007
// ini.rc
#include "resource.h"
#include "afxres.h"
//
// Dialog
//
IDD_MAIN DIALOG DISCARDABLE 0, 0, 290, 222
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "读写Ini文件"
FONT 10, "宋体"
BEGIN
RTEXT "Section",IDC_STATIC,14,18,33,8
RTEXT "Key",IDC_STATIC,12,42,35,8
RTEXT "Value",IDC_STATIC,12,66,35,8
EDITTEXT IDC_SEC,58,15,110,14,ES_AUTOHSCROLL
EDITTEXT IDC_KEY,58,37,110,14,ES_AUTOHSCROLL
EDITTEXT IDC_VALUE,58,61,111,14,ES_AUTOHSCROLL
PUSHBUTTON "删除&Section",IDC_DEL_SEC,178,14,50,14
PUSHBUTTON "删除&Key",IDC_DEL_KEY,233,14,50,14
PUSHBUTTON "读取K&ey",IDC_GET_KEY,178,37,50,14
PUSHBUTTON "保存Ke&y",IDC_SET_KEY,233,37,50,14
LTEXT "当前ini文件内容:",IDC_STATIC,7,88,73,8
EDITTEXT IDC_INI,7,103,276,112,ES_MULTILINE | ES_AUTOVSCROLL |
ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
END
关于上面用的api函数的具体用法,你可以参看msdn,上面有详细的解释。
本文程序改写自罗云彬32位汇编语言一书中的例程。
author:cnhnyu
e-mail:cnhnyu<AT>gmail<DOT>com
qq:94483026
Windows为了很好的读写这类文件,提供了一些专门的读写函数,我们在自己的应用程序中可以充分的利用这些函数来保存一些比较简单的配置信息。
Windows的ini文件结构一般如下:
; 注释部分,以分号开头
[Section1]
key1=name1
key2=name2
;每个节(section)以方括号括起来,每个section下面可以有0到多个key
;以key=value的形式书写,=前面是key的名称,=后面是key的value
[Section2]
key3=value3
key4=value4
从上面可以看出一个ini文件主要有3部分组成,以分号开始的注释,以方括号括起来的节(section)以及在每个节下面的以key=value形式的键,在同一个section下面key的名称必须唯一,在不同的section下面可以相同,在整个ini文件中section的名称不能重复。
ini文件的结构很简单,下面的程序,演示了如何用windows提供的api进行读写.
新建一个VC6++win32的空的工程,添入以下文件:
/*
FileName: ini.c
Function: Read and write ini file
Desc: Windows 32 bits Application
本程序演示了如何读写ini文件,ini文件是一种特殊的文本文件,它的结构如下:
; comment
[Section1]
Key1=value1
Key2=value2
[Section2]
;keys
Key3=value3
Key4=value4
......
*/
#include <windows.h>
#include "resource.h"
HWND hWinMain = NULL; // 主对话框句柄
char szProfileName[MAX_PATH]; // 用来保存ini文件的全路径名称
char szBuffer1[32760]; // 用来保存读取的Sections
char szBuffer2[32760]; // 用来保存读取的Keys
char szFileName[] = TEXT("\\Option.ini"); // ini 文件名称
char szSecPos[] = TEXT("Windows Position");
char szKeyX[] = TEXT("X");
char szKeyY[] = TEXT("Y");
char szFmt1[] = TEXT("%d");
char szFmtSection[] = TEXT("[%s]");
char szCrLf[] = "\r\n"; // 回车换行
void EnumIni(); // 读取ini文件,枚举所有的sections以及keys
void GetPosition(); // 获取对话框的坐标
void SavePosition(); // 保存对话框的坐标
LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd )
{
DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DialogProc, 0);
return 0;
}
void EnumIni()
{
char szBuffer[256];
char *p, *q;
SetDlgItemText(hWinMain, IDC_INI, NULL);
// 得到所有的sections,每个section都是以0结尾的字符串,最后整个字符串以0结尾
GetPrivateProfileSectionNames(szBuffer1, sizeof(szBuffer1), szProfileName);
p = szBuffer1; // 指向szBuffer1中的第一个Section
while ( p[0] ) // 循环读取section
{
wsprintf(szBuffer, szFmtSection, p);
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)szBuffer);
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)szCrLf);
// 得到该Section下面的所有keys
// 每个key都是以0结尾的字符串,最后整个字符串以0 结尾
GetPrivateProfileSection(p, szBuffer2, sizeof(szBuffer2), szProfileName);
q = szBuffer2; // 指向第一个key
while ( q[0] ) // 循环读取所有的keys
{
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)q);
SendDlgItemMessage(hWinMain, IDC_INI, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)szCrLf);
q += strlen(q) + 1; // 指针移动到下一个key
}
p += strlen(p) + 1; // 指针移动到下一个section
}
}
void GetPosition()
{
int x, y;
// 获取当前的路径
GetCurrentDirectory(MAX_PATH, szProfileName);
// 得到ini文件的全路径
lstrcat(szProfileName, szFileName);
// 得到位置section的坐标值,如果失败,则默认为(50, 50)
x = GetPrivateProfileInt(szSecPos, szKeyX, 50, szProfileName);
y = GetPrivateProfileInt(szSecPos, szKeyY, 50, szProfileName);
// 设置对话框的位置
SetWindowPos(hWinMain, HWND_TOP, x, y, 0, 0, SWP_NOSIZE);
}
void SavePosition()
{
char szBuffer[512];
RECT rc;
// 得到窗口的坐标, 并切保存到ini文件
GetWindowRect(hWinMain, &rc);
wsprintf(szBuffer, szFmt1, rc.left);
WritePrivateProfileString(szSecPos, szKeyX, szBuffer, szProfileName);
wsprintf(szBuffer, szFmt1, rc.top);
WritePrivateProfileString(szSecPos, szKeyY, szBuffer, szProfileName);
}
LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char szSection[256];
char szKey[256];
char szValue[256];
char szBuffer[256];
switch ( uMsg )
{
case WM_CLOSE: // 对话框关闭保存对话框的位置
SavePosition();
EndDialog(hWnd, 0);
break;
case WM_INITDIALOG: // 对话框初始化,得到对话框的原来位置,并且读取ini文件
hWinMain = hWnd;
GetPosition();
EnumIni(); // 枚举ini文件的内容
break;
case WM_COMMAND:
GetDlgItemText(hWnd, IDC_SEC, szSection, sizeof(szSection));
GetDlgItemText(hWnd, IDC_KEY, szKey, sizeof(szKey));
GetDlgItemText(hWnd, IDC_VALUE, szValue, sizeof(szValue));
switch ( LOWORD(wParam) )
{
case IDC_SEC:
case IDC_KEY:
case IDC_VALUE:
case IDC_INI:
return TRUE;
case IDC_DEL_SEC: // 删除一个section
WritePrivateProfileString(szSection, NULL, NULL, szProfileName);
break;
case IDC_DEL_KEY: // 删除一个key
WritePrivateProfileString(szSection, szKey, NULL, szProfileName);
break;
case IDC_SET_KEY: // 保存一个key
WritePrivateProfileString(szSection, szKey, szValue, szProfileName);
break;
case IDC_GET_KEY: // 得到一个key
GetPrivateProfileString(szSection, szKey, NULL, szBuffer, sizeof(szBuffer), szProfileName);
SetDlgItemText(hWnd, IDC_VALUE, szBuffer);
break;
default:
break;
}
EnumIni(); // 更新ini文件的显示信息
break;
default:
return FALSE;
}
return TRUE;
}
//resource.h
#define IDD_MAIN 101
#define IDC_SEC 1000
#define IDC_KEY 1001
#define IDC_VALUE 1002
#define IDC_DEL_SEC 1003
#define IDC_DEL_KEY 1004
#define IDC_GET_KEY 1005
#define IDC_SET_KEY 1006
#define IDC_INI 1007
// ini.rc
#include "resource.h"
#include "afxres.h"
//
// Dialog
//
IDD_MAIN DIALOG DISCARDABLE 0, 0, 290, 222
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "读写Ini文件"
FONT 10, "宋体"
BEGIN
RTEXT "Section",IDC_STATIC,14,18,33,8
RTEXT "Key",IDC_STATIC,12,42,35,8
RTEXT "Value",IDC_STATIC,12,66,35,8
EDITTEXT IDC_SEC,58,15,110,14,ES_AUTOHSCROLL
EDITTEXT IDC_KEY,58,37,110,14,ES_AUTOHSCROLL
EDITTEXT IDC_VALUE,58,61,111,14,ES_AUTOHSCROLL
PUSHBUTTON "删除&Section",IDC_DEL_SEC,178,14,50,14
PUSHBUTTON "删除&Key",IDC_DEL_KEY,233,14,50,14
PUSHBUTTON "读取K&ey",IDC_GET_KEY,178,37,50,14
PUSHBUTTON "保存Ke&y",IDC_SET_KEY,233,37,50,14
LTEXT "当前ini文件内容:",IDC_STATIC,7,88,73,8
EDITTEXT IDC_INI,7,103,276,112,ES_MULTILINE | ES_AUTOVSCROLL |
ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
END
关于上面用的api函数的具体用法,你可以参看msdn,上面有详细的解释。
本文程序改写自罗云彬32位汇编语言一书中的例程。
author:cnhnyu
e-mail:cnhnyu<AT>gmail<DOT>com
qq:94483026