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,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,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,IniFileName) If ReturnLng = 0 Then ReturnLng = GetPrivateProfileInt(Section,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 已经帮我们做了