VB.NET 操作 INI 文件类

INI 文件是一种经典的配置文件格式,广泛应用于 Windows 系统中。尽管现在更多应用转向 XML、JSON 或注册表等配置方式,INI 文件因其简单易读、易于手工修改的特点,仍在很多场景下被使用。本文将详细介绍如何在 VB.NET 中通过封装 Windows API 函数来读写 INI 文件,并提供一个功能完善的类实例。

一、INI 文件结构简介

INI 文件是一种简单的文本文件,其基本结构由节(Section)、键(Key)和值(Value)组成。例如:

ini 复制代码
[Database]
Server=localhost
Port=3306
Username=admin

[Settings]
AutoStart=true
Theme=Dark

二、VB.NET 操作 INI 文件的实现原理

VB.NET 中,操作 INI 文件主要通过调用 Windows API 中的 kernel32.dll 提供的函数来实现。这些函数包括:

  • WritePrivateProfileString:写入字符串值
  • GetPrivateProfileString:读取字符串值
  • WritePrivateProfileStruct:写入结构体数据
  • GetPrivateProfileStruct:读取结构体数据

三、完整的 VB.NET INI 操作类详解

下面是一个完整的 VB.NET 类,封装了对 INI 文件的各种操作,并添加了详细的中文注释:

vbnet 复制代码
Imports System
Imports System.Text
Imports System.Runtime.InteropServices

Namespace Lob_ini
    ''' <summary>
    ''' INI 文件操作类
    ''' </summary>
    Public Class cIni
        ' 定义 INI 文件路径
        Private ls_IniFilename As String
        ' 定义读取缓冲区长度,默认256字节
        Private li_BufferLen As Integer = 256

        ''' <summary>
        ''' 构造函数,初始化 INI 文件路径
        ''' </summary>
        ''' <param name="pIniFilename">INI 文件完整路径</param>
        Public Sub New(ByVal pIniFilename As String)
            MyBase.New()
            ls_IniFilename = pIniFilename
        End Sub

        ''' <summary>
        ''' INI 文件路径属性
        ''' </summary>
        Public Property IniFile() As String
            Get
                Return ls_IniFilename
            End Get
            Set(ByVal value As String)
                ls_IniFilename = value
            End Set
        End Property

        ''' <summary>
        ''' 缓冲区长度属性(最大值32767)
        ''' </summary>
        Public Property BufferLen() As Integer
            Get
                Return li_BufferLen
            End Get
            Set(ByVal value As Integer)
                ' 限制缓冲区长度在合理范围内
                If (value > 32767) Then
                    li_BufferLen = 32767
                ElseIf (value < 1) Then
                    li_BufferLen = 1
                Else
                    li_BufferLen = value
                End If
            End Set
        End Property

        ' 声明 Windows API 函数 - 写入字符串到 INI 文件
        Private Declare Function WritePrivateProfileString Lib "kernel32" (
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal pValue As String, 
            ByVal pFile As String) As Integer

        ' 声明 Windows API 函数 - 写入结构体到 INI 文件
        Private Declare Function WritePrivateProfileStruct Lib "kernel32" (
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal pValue As String, 
            ByVal pValueLen As Integer, 
            ByVal pFile As String) As Integer

        ' 声明 Windows API 函数 - 从 INI 文件读取字符串
        Private Declare Function GetPrivateProfileString Lib "kernel32" (
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal pDefault As String, 
            ByVal prReturn() As Byte, 
            ByVal pBufferLen As Integer, 
            ByVal pFile As String) As Integer

        ' 声明 Windows API 函数 - 从 INI 文件读取结构体
        Private Declare Function GetPrivateProfileStruct Lib "kernel32" (
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal prReturn() As Byte, 
            ByVal pBufferLen As Integer, 
            ByVal pFile As String) As Integer

        ''' <summary>
        ''' 从 INI 文件读取指定键的值
        ''' </summary>
        ''' <param name="pSection">节名称</param>
        ''' <param name="pKey">键名称</param>
        ''' <param name="pDefault">默认值</param>
        ''' <returns>读取到的值或默认值</returns>
        Public Overloads Function ReadValue(
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal pDefault As String) As String
            Return z_GetString(pSection, pKey, pDefault)
        End Function

        ''' <summary>
        ''' 从 INI 文件读取指定键的值(默认值为空字符串)
        ''' </summary>
        ''' <param name="pSection">节名称</param>
        ''' <param name="pKey">键名称</param>
        ''' <returns>读取到的值或空字符串</returns>
        Public Overloads Function ReadValue(
            ByVal pSection As String, 
            ByVal pKey As String) As String
            Return z_GetString(pSection, pKey, "")
        End Function

        ''' <summary>
        ''' 向 INI 文件写入键值对
        ''' </summary>
        ''' <param name="pSection">节名称</param>
        ''' <param name="pKey">键名称</param>
        ''' <param name="pValue">要写入的值</param>
        Public Sub WriteValue(
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal pValue As String)
            WritePrivateProfileString(pSection, pKey, pValue, Me.ls_IniFilename)
        End Sub

        ''' <summary>
        ''' 从 INI 文件删除指定键
        ''' </summary>
        ''' <param name="pSection">节名称</param>
        ''' <param name="pKey">键名称</param>
        Public Sub RemoveValue(
            ByVal pSection As String, 
            ByVal pKey As String)
            WritePrivateProfileString(pSection, pKey, Nothing, Me.ls_IniFilename)
        End Sub

        ''' <summary>
        ''' 读取指定节中的所有键值对
        ''' </summary>
        ''' <param name="pSection">节名称</param>
        ''' <param name="pValues">返回的键值对数组</param>
        Public Sub ReadValues(
            ByVal pSection As String, 
            ByRef pValues As Array)
            pValues = z_GetString(pSection, Nothing, Nothing).Split(CType(ChrW(0), Char))
        End Sub

        ''' <summary>
        ''' 读取 INI 文件中的所有节名称
        ''' </summary>
        ''' <param name="pSections">返回的节名称数组</param>
        Public Sub ReadSections(ByRef pSections As Array)
            pSections = z_GetString(Nothing, Nothing, Nothing).Split(CType(ChrW(0), Char))
        End Sub

        ''' <summary>
        ''' 从 INI 文件中删除整个节
        ''' </summary>
        ''' <param name="pSection">要删除的节名称</param>
        Public Sub RemoveSection(ByVal pSection As String)
            WritePrivateProfileString(pSection, Nothing, Nothing, Me.ls_IniFilename)
        End Sub

        ''' <summary>
        ''' 内部方法:调用 GetPrivateProfileString API 读取数据
        ''' </summary>
        Private Function z_GetString(
            ByVal pSection As String, 
            ByVal pKey As String, 
            ByVal pDefault As String) As String
            Dim sRet As String = pDefault
            ' 创建字节数组作为缓冲区
            Dim bRet() As Byte = New Byte((li_BufferLen) - 1) {}
            ' 调用 API 读取数据
            Dim i As Integer = GetPrivateProfileString(
                pSection, pKey, pDefault, bRet, li_BufferLen, ls_IniFilename)
            ' 将字节数组转换为字符串并去除末尾的空字符
            sRet = System.Text.Encoding.GetEncoding(1252).GetString(bRet, 0, i).TrimEnd(CType(ChrW(0), Char))
            Return sRet
        End Function
    End Class
End Namespace

四、类关系图

下面是 cIni 类的 UML 类图,展示了其主要属性和方法:
cIni -String ls_IniFilename -Integer li_BufferLen +Property IniFile: String +Property BufferLen: Integer +New(pIniFilename: String) +ReadValue(pSection: String, pKey: String, pDefault: String) : String +ReadValue(pSection: String, pKey: String) : String +WriteValue(pSection: String, pKey: String, pValue: String) +RemoveValue(pSection: String, pKey: String) +ReadValues(pSection: String, ByRef pValues: Array) +ReadSections(ByRef pSections: Array) +RemoveSection(pSection: String) -z_GetString(pSection: String, pKey: String, pDefault: String) : String

五、使用示例

下面是如何使用上述 cIni 类来操作 INI 文件的示例:

vb 复制代码
' 创建 cIni 实例,指定 INI 文件路径
Dim iniFile As New cIni("C:\config.ini")

' 写入配置值
iniFile.WriteValue("Database", "Server", "localhost")
iniFile.WriteValue("Database", "Port", "3306")

' 读取配置值
Dim server As String = iniFile.ReadValue("Database", "Server", "default_server")
Dim port As Integer = CInt(iniFile.ReadValue("Database", "Port", "1433"))

' 读取整个节的所有键
Dim values As Array = Nothing
iniFile.ReadValues("Database", values)

' 删除某个键
iniFile.RemoveValue("Database", "Port")

' 删除整个节
iniFile.RemoveSection("Database")

六、注意事项与最佳实践

  1. 路径问题:如果未指定完整路径,INI 文件通常会位于 Windows 目录下。
  2. 缓冲区大小:读取大量数据时,适当增加缓冲区大小可以提高性能,但最大不超过 32767。
  3. 编码问题:INI 文件通常使用 ANSI 编码(代码页1252),如果需要支持 Unicode,需要考虑使用其他方法。
  4. 错误处理:在实际应用中,应该添加适当的错误处理机制。
  5. 性能考虑:频繁读写 INI 文件可能影响性能,可以考虑缓存机制。

七、扩展功能建议

  1. 添加缓存机制:将读取的数据缓存到内存中,减少文件 I/O 操作。
  2. 支持类型转换:添加对整数、布尔值等数据类型的自动转换支持。
  3. 添加事件通知:当 INI 文件被修改时,触发相应的事件。
  4. 支持注释:添加对 INI 文件中注释的读取和保留功能。
  5. 线程安全:如果需要在多线程环境中使用,添加线程安全机制。

单词、短语表

单词(短语) 音标 词性 词根/词缀 释义 搭配 例子
Constructor [kənˈstrʌktə] n. con-(共同)+ struct(建造)+ -or(人/物) 构造函数 class constructor The constructor initializes the object.
Property [ˈprɒpəti] n. proper(自己的)+ -ty(名词后缀) 属性 object property The Name property stores the object's name.
Buffer [ˈbʌfə] n. - 缓冲区 buffer size, buffer overflow Increase the buffer size for better performance.
Declare [dɪˈkleə] v. de-(完全)+ clar(清楚)+ -e 声明 declare function, declare variable You need to declare the API function first.
Overloads [ˌəʊvəˈləʊdz] v. over-(超过)+ load(负载) 重载 method overloads The method overloads provide different parameter options.
Encoding [ɪnˈkəʊdɪŋ] n. en-(使)+ code(代码)+ -ing 编码 character encoding, encoding format Use proper encoding for multilingual support.
TrimEnd [trɪm end] v. trim(修剪)+ end(末端) 修剪末尾 trim end characters TrimEnd removes trailing characters.
Kernel32 [ˈkɜːnəl θɜːti tuː] n. - Windows 内核库 kernel32.dll Kernel32 provides core Windows functionality.
Private [ˈpraɪvɪt] adj. priv(私有)+ -ate 私有的 private method, private variable Private members are accessible only within the class.

VB.NET 项目中有效地使用 INI 文件进行配置管理。这个类封装了基本的 INI 文件操作功能,可以根据实际需求进行扩展和优化。

相关推荐
万邦科技Lafite1 天前
如何通过第三方API接口获取拼多多店铺信息?
api·开放api·电商开放平台·拼多多开放平台
天远云服1 天前
从异步调用到风控应用:Node.js开发者接入天远API全流程
api
代码方舟3 天前
Java开发者如何接入天远API多头借贷风险评估接口
api
課代表6 天前
VB.NET 与 C# 文件操作文本到二进制文件的读写
c#·二进制文件·vb.net·streamwriter·文本文件·读写·streamreader
电商api24677428107 天前
亚马逊API接口全面指南
api
电商api24677428107 天前
全网最全面介绍唯品会API接口指南
api
电商api24677428107 天前
全网最全面介绍闲鱼API接口指南
api
迦蓝叶8 天前
JAiRouter v1.1.0 发布:把“API 调没调通”从 10 分钟压缩到 10 秒
java·人工智能·网关·openai·api·协议归一