INI 文件就是 Windows 中常见的以 .ini 为扩展名的文件,其内部格式和各部分的名称如下:
[Section1]
Key1=Value1
Key2=Value2
Key3=Vlaue3
[Section2]
Key1=Value1
Key2=Value5
Key4=Value4
Key5=...
...
INI 文件中分若干个段 (Section),每个段中有若干个键 (Key) 值 (Value) 对
。一个键值对保存一个信息;段则将属性类似的一些键值对组织在一起。同一个段中不
能出现两次以上同样的键,但不同的段中可以出现相同的键。
现在明白了吗?要是还不明白,就到 Windows 里找两个 INI 文件看看,文本编辑
器就可以打开的。明白了 INI 文件就要开始学习怎样在 VB 中读写 INI 了。
VB 读写 INI 文件,难吗?不难,因为 Windows 已经为我们做好了一切,我们只
需要调用它的 API 函数就可以了。为了读写 INI 文件,我们可能用到以下 API 函数
:
GetPrivateProfileInt
GetPrivateProfileString
WritePrivateProfileString
其中 WritePrivateProfileString 是用来向 INI 文件写信息的,而
GetPrivateProfileInt 和 GetPrivateProfileString 则是用来从 INI 文件中读信息
的,前者用于读取整型数据,后者则用于读取字符串型数据。
上述三个 API 函数在 VB 中的申明和说明如下:
Private Declare Function GetPrivateProfileInt Lib "kernel32" _
Alias "GetPrivateProfileIntA" ( _ ' 返回所读取的长整型值
ByVal lpApplicationName As String, _ ' 要读取的段 (Section) 名称
ByVal lpKeyName As String, _ ' 要读取的的键 (Key) 名称
ByVal nDefault As Long, _ ' 指定默认值,如果读取时出错,则返回该值
ByVal lpFileName As String) As Long ' 指定要读的 INI 文件名
Private Declare Function GetPrivateProfileString Lib "kernel32" _
Alias "GetPrivateProfileStringA" ( _ ' 返回所读取的字符串值的真实长度
ByVal lpApplicationName As String, _ ' 要读取的段 (Section) 名称
ByVal lpKeyName As Any, _ ' 要读取的的键 (Key) 名称
ByVal lpDefault As String, _ ' 指定默认值,如果读取时出错,则返回该值
ByVal lpReturnedString As String, _ ' 指定接收返回值的字符串变量
ByVal nSize As Long, _ ' 指定允许字符串值的最大长度
ByVal lpFileName As String) As Long ' 指定要读的 INI 文件名
Private Declare Function WritePrivateProfileString Lib "kernel32" _
Alias "WritePrivateProfileStringA" ( _ ' 如果成功返回非 0 值,失败返回 0
ByVal lpApplicationName As String, _ ' 要写入的段 (Section) 名称
ByVal lpKeyName As Any, _ ' 要写入的的键 (Key) 名称
ByVal lpString As Any, _ ' 要写入的值 (Value),以字符串表示
ByVal lpFileName As String) As Long ' 指定要写的 INI 文件名
我们的目的是要在 VB 中写一个读写 INI 文件的类,所以在 VB 中新建一个工程,并添加一个类模块 (Class Module),命令类为 CIniFile,并且将上面的申明添加到类模块中。然后开始为类添加属性和方法。
从上面的注释说明中,我们可以知道,每次调三个 API 之一都需要指定 INI 文件
名。而在我们的 CIniFile 的每一个实例中,应该始终访问同一个 INI 文件,所以属
性之一就是文件名:
Private IniFileName As String
另外,调用 API 的过程中可能会出现错误,那么 CIniFile 应该能提供错误信息
,所以定义一个保存错误信息的变量作为 CIniFile 的第二个属性
Public ErrorMsg As String
由于访问什么段、什么键以及写入什么值都可以通过参数的形式传递给方法,而获
取的值也都可以通过方法的返回值得以,所以不再需要其它属性了。不过在定义方法之
前还需要对属性进行初始化:
Private Sub Class_Initialize() IniFileName = vbNullString ErrorMsg = vbNullString End Sub
为了指定 INI 文件名给 CIniFile,需要定义一个方法:
Public Sub SpecifyIni(FilePathName) IniFileName = Trim(FilePathName) End Sub
在每次读写值之前还需要先判断是否已经指定了 INI 文件名,不然读什么写什么啊
?
Private Function NoIniFile() As Boolean NoIniFile = True If IniFileName = vbNullString Then ErrorMsg = "没有指定 INI 文件" Exit Function End If ErrorMsg = vbNullString NoIniFile = False End Function 准备工作完成,现在才是重头戏,读写 INI 文件。似乎“写”要简单一些,就先“
写”吧:
Public Function WriteString(Section As String, key As String, Value As String) As Boolean WriteString = False If NoIniFile() Then Exit Function End If If WritePrivateProfileString(Section, key, Value, IniFileName) = 0 Then ErrorMsg = "写入失败" Exit Function End If WriteString = True End Function 该方法在 INI 文件中写入一个键值,成功返回 True,失败返回 False。根据
WritePrivateProfileString 的需要,除了文件名这一参数不用提供之外,需要提供段
名、键名和值三个参数,而且这三个参数当然来自用户。而
WritePrivateProfileString 是通过返回值是否为 0 来判断是否成功的,所以可以通
过判断 WritePrivateProfileString 的返回值是否非 0 来返回 True 或 False。
而读 INI 就要稍稍麻烦一点了,两个读取 INI 文件的的函数中,读取字符串那个
虽然参数多些,但实现起来却更简单,所以,先写这个:
Public Function ReadString(Section As String, key As String, Size As Long) As String Dim ReturnStr As String Dim ReturnLng As Long ReadString = vbNullString If NoIniFile() Then Exit Function End If ReturnStr = Space(Size) ReturnLng = GetPrivateProfileString(Section, key, vbNullString, ReturnStr, Size, IniFileName) ReadString = Left(ReturnStr, ReturnLng) End Function 这个方法在 INI 文件中读取一个键值,作为字符串返回。如果参数 Size 给定的
大小不够,将不能返回完整的值串,但不会有任何提示。
写这个函数的关键在 ReturnStr 的初始化和取值上。VB 中是不需要对字符串进行
初始化的,也不需要分配空间。但是这里如果不将它初始化为一个足够长的字符串,就
不能正确返回结果。这和 C 语言的字符串有关,就不多说了。ReturnStr 的取值也需要
有趣,要使用 Left() 函数将其截断。如果不截断,取得的结果字符串就会有 Size 那
幺长,除了取得的值以外,其余部分都是用空格填充的。其原因与前面一点相同,与 C
语言的字符串有关。当然 Left() 函数也可以使用 Trim() 代替,效果是一样的。
最后我们不得不面对这个最麻烦的 ReadInt 方法了。它为什么麻烦呢?看看现在的
函数定义就知道了:
Public Function ReadInt(Section As String, key As String) As Long Dim ReturnLng As Long ReadInt = 0 ReturnLng = GetPrivateProfileInt(Section, key, 0, IniFileName) If ReturnLng = 0 Then ReturnLng = GetPrivateProfileInt(Section, key, 1, IniFileName) If ReturnLng = 1 Then ErrorMsg = "不能读取" Exit Function End If End If ReadInt = ReturnLng End Function 这个方法在 INI 文件中读取一个整数值,失败时返回 0。考虑到某些键的值也可能
为 0,故应结合 ErrorMsg 判断是否成功。
这个方法中调用了两次 GetPrivateProfileInt,为什么要这样呢?因为
GetPrivateProfileInt 如果成功则返回取得的值,如果不成功则返回给定的默认值。
这样就会出现一种情况:如果我给的默认值是 0,GetPrivateProfileInt 函数取得的
值也是 0,那么它是成功还是失败呢?同样,如果我给的默认值是
1,GetPrivateProfileInt 函数取得的值也是 1,那就是成功还是失败呢?既然一次取
值无法判断,那就多取一次,第一次设定默认值为 0,第二次设定默认值为 1,INI 文
件的中值不会跟着我的默认值变吧?!虽然这样麻烦一些,但毕竟把问题解决了。
自此,我们终于把一个 CIniFile 写完了——现在读写 INI 文件再也不需要像写
CIniFile 一样考虑许多东西了,CIniFile 已经帮我们做了