当前位置:  开发笔记 > 编程语言 > 正文

现代,unicode友好的".ini文件",用于在VB6中存储配置数据

如何解决《现代,unicode友好的".ini文件",用于在VB6中存储配置数据》经验,为你挑选了3个好方法。

我想将数据结构的内容,几个数组和十几个变量存储在一个文件中,该文件可以由我的软件保存和重新加载,也可以由用户重新加载在文本编辑器中编辑.对于文本编辑,我需要清楚地标记数据,就像在一个好的ole .ini文件中一样:

AbsMaxVoltage = 17.5

有一个GUI,可以说用户应该只从GUI加载,保存和修改,但客户希望能够以文本的形式读取和修改数据.

编写代码来保存并重新加载它很容易(假设所有标签都在同一个地方且只有数据发生了变化).随着更多的工作(或使用一些已经在那里的INI R/W代码,我可以关注标签,所以如果一行被删除或移动变量仍然填充正确,但这两种方法看起来都很旧 - 所以我对今天编程中最聪明的人会如何接近这一点很感兴趣(使用十年前的VB6,我必须承认我仍然喜欢).

免责声明:我是电气工程师,不是程序员.这不是我的日常工作.好吧也许这是我日常工作的几个百分点.

干杯!



1> Jason Cohen..:

考虑使用XML.它是完全标准的,许多文本编辑器将正确地突出/管理它,地球上的每种编程语言和脚本语言都有很好的阅读支持,它完美地处理Unicode.

对于您建议的简单名称/值对,它非常易读.但是你有一个额外的好处,即如果有一天你需要更复杂的东西 - 例如多行值或一系列不同的值 - XML提供了自然,简单的表示方式.

PS 以下是如何在VB6中读取XML.



2> Jay Riggs..:

回到过去,这堂课帮助我在我的VB6程序中使用INI文件:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "cInifile"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
' =========================================================
' Class:    cIniFile
' Author:   Steve McMahon
' Date  :   21 Feb 1997
'
' A nice class wrapper around the INIFile functions
' Allows searching,deletion,modification and addition
' of Keys or Values.
'
' Updated 10 May 1998 for VB5.
'   * Added EnumerateAllSections method
'   * Added Load and Save form position methods
' =========================================================

Private m_sPath As String
Private m_sKey As String
Private m_sSection As String
Private m_sDefault As String
Private m_lLastReturnCode As Long

#If Win32 Then
    ' Profile String functions:
    Private Declare Function WritePrivateProfileString Lib "KERNEL32" Alias
     "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal
     lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As
     Long
    Private Declare Function GetPrivateProfileString Lib "KERNEL32" Alias
     "GetPrivateProfileStringA" (ByVal lpApplicationName As Any, ByVal
     lpKeyName As Any, ByVal lpDefault As Any, ByVal lpReturnedString As
     String, ByVal nSize As Long, ByVal lpFileName As String) As Long
#Else
    ' Profile String functions:
    Private Declare Function WritePrivateProfileString Lib "Kernel" (ByVal
     lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As
     Any, ByVal lpFileName As String) As Integer
    Private Declare Function GetPrivateProfileString Lib "Kernel" (ByVal
     lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As
     Any, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal
     lpFileName As String) As Integer
#End If

Property Get LastReturnCode() As Long
    LastReturnCode = m_lLastReturnCode
End Property
Property Get Success() As Boolean
    Success = (m_lLastReturnCode <> 0)
End Property
Property Let Default(sDefault As String)
    m_sDefault = sDefault
End Property
Property Get Default() As String
    Default = m_sDefault
End Property
Property Let Path(sPath As String)
    m_sPath = sPath
End Property
Property Get Path() As String
    Path = m_sPath
End Property
Property Let Key(sKey As String)
    m_sKey = sKey
End Property
Property Get Key() As String
    Key = m_sKey
End Property
Property Let Section(sSection As String)
    m_sSection = sSection
End Property
Property Get Section() As String
    Section = m_sSection
End Property
Property Get Value() As String
Dim sBuf As String
Dim iSize As String
Dim iRetCode As Integer

    sBuf = Space$(255)
    iSize = Len(sBuf)
    iRetCode = GetPrivateProfileString(m_sSection, m_sKey, m_sDefault, sBuf,
     iSize, m_sPath)
    If (iSize > 0) Then
        Value = Left$(sBuf, iRetCode)
    Else
        Value = ""
    End If

End Property
Property Let Value(sValue As String)
Dim iPos As Integer
    ' Strip chr$(0):
    iPos = InStr(sValue, Chr$(0))
    Do While iPos <> 0
        sValue = Left$(sValue, (iPos - 1)) & Mid$(sValue, (iPos + 1))
        iPos = InStr(sValue, Chr$(0))
    Loop
    m_lLastReturnCode = WritePrivateProfileString(m_sSection, m_sKey, sValue,
     m_sPath)
End Property
Public Sub DeleteKey()
    m_lLastReturnCode = WritePrivateProfileString(m_sSection, m_sKey, 0&,
     m_sPath)
End Sub
Public Sub DeleteSection()
    m_lLastReturnCode = WritePrivateProfileString(m_sSection, 0&, 0&, m_sPath)
End Sub
Property Get INISection() As String
Dim sBuf As String
Dim iSize As String
Dim iRetCode As Integer

    sBuf = Space$(8192)
    iSize = Len(sBuf)
    iRetCode = GetPrivateProfileString(m_sSection, 0&, m_sDefault, sBuf, iSize,
     m_sPath)
    If (iSize > 0) Then
        INISection = Left$(sBuf, iRetCode)
    Else
        INISection = ""
    End If

End Property
Property Let INISection(sSection As String)
    m_lLastReturnCode = WritePrivateProfileString(m_sSection, 0&, sSection,
     m_sPath)
End Property
Property Get Sections() As String
Dim sBuf As String
Dim iSize As String
Dim iRetCode As Integer

    sBuf = Space$(8192)
    iSize = Len(sBuf)
    iRetCode = GetPrivateProfileString(0&, 0&, m_sDefault, sBuf, iSize, m_sPath)
    If (iSize > 0) Then
        Sections = Left$(sBuf, iRetCode)
    Else
        Sections = ""
    End If

End Property
Public Sub EnumerateCurrentSection(ByRef sKey() As String, ByRef iCount As Long)
Dim sSection As String
Dim iPos As Long
Dim iNextPos As Long
Dim sCur As String

    iCount = 0
    Erase sKey
    sSection = INISection
    If (Len(sSection) > 0) Then
        iPos = 1
        iNextPos = InStr(iPos, sSection, Chr$(0))
        Do While iNextPos <> 0
            sCur = Mid$(sSection, iPos, (iNextPos - iPos))
            If (sCur <> Chr$(0)) Then
                iCount = iCount + 1
                ReDim Preserve sKey(1 To iCount) As String
                sKey(iCount) = Mid$(sSection, iPos, (iNextPos - iPos))
                iPos = iNextPos + 1
                iNextPos = InStr(iPos, sSection, Chr$(0))
            End If
        Loop
    End If
End Sub
Public Sub EnumerateAllSections(ByRef sSections() As String, ByRef iCount As
 Long)
Dim sIniFile As String
Dim iPos As Long
Dim iNextPos As Long
Dim sCur As String

    iCount = 0
    Erase sSections
    sIniFile = Sections
    If (Len(sIniFile) > 0) Then
        iPos = 1
        iNextPos = InStr(iPos, sIniFile, Chr$(0))
        Do While iNextPos <> 0
            If (iNextPos <> iPos) Then
                sCur = Mid$(sIniFile, iPos, (iNextPos - iPos))
                iCount = iCount + 1
                ReDim Preserve sSections(1 To iCount) As String
                sSections(iCount) = sCur
            End If
            iPos = iNextPos + 1
            iNextPos = InStr(iPos, sIniFile, Chr$(0))
        Loop
    End If

End Sub
Public Sub SaveFormPosition(ByRef frmThis As Object)
Dim sSaveKey As String
Dim sSaveDefault As String
On Error GoTo SaveError
    sSaveKey = Key
    If Not (frmThis.WindowState = vbMinimized) Then
        Key = "Maximised"
        Value = (frmThis.WindowState = vbMaximized) * -1
        If (frmThis.WindowState <> vbMaximized) Then
            Key = "Left"
            Value = frmThis.Left
            Key = "Top"
            Value = frmThis.Top
            Key = "Width"
            Value = frmThis.Width
            Key = "Height"
            Value = frmThis.Height
        End If
    End If
    Key = sSaveKey
    Exit Sub
SaveError:
    Key = sSaveKey
    m_lLastReturnCode = 0
    Exit Sub
End Sub
Public Sub LoadFormPosition(ByRef frmThis As Object, Optional ByRef lMinWidth =
 3000, Optional ByRef lMinHeight = 3000)
Dim sSaveKey As String
Dim sSaveDefault As String
Dim lLeft As Long
Dim lTOp As Long
Dim lWidth As Long
Dim lHeight As Long
On Error GoTo LoadError
    sSaveKey = Key
    sSaveDefault = Default
    Default = "FAIL"
    Key = "Left"
    lLeft = CLngDefault(Value, frmThis.Left)
    Key = "Top"
    lTOp = CLngDefault(Value, frmThis.Top)
    Key = "Width"
    lWidth = CLngDefault(Value, frmThis.Width)
    If (lWidth < lMinWidth) Then lWidth = lMinWidth
    Key = "Height"
    lHeight = CLngDefault(Value, frmThis.Height)
    If (lHeight < lMinHeight) Then lHeight = lMinHeight
    If (lLeft < 4 * Screen.TwipsPerPixelX) Then lLeft = 4 *
     Screen.TwipsPerPixelX
    If (lTOp < 4 * Screen.TwipsPerPixelY) Then lTOp = 4 * Screen.TwipsPerPixelY
    If (lLeft + lWidth > Screen.Width - 4 * Screen.TwipsPerPixelX) Then
        lLeft = Screen.Width - 4 * Screen.TwipsPerPixelX - lWidth
        If (lLeft < 4 * Screen.TwipsPerPixelX) Then lLeft = 4 *
         Screen.TwipsPerPixelX
        If (lLeft + lWidth > Screen.Width - 4 * Screen.TwipsPerPixelX) Then
            lWidth = Screen.Width - lLeft - 4 * Screen.TwipsPerPixelX
        End If
    End If
    If (lTOp + lHeight > Screen.Height - 4 * Screen.TwipsPerPixelY) Then
        lTOp = Screen.Height - 4 * Screen.TwipsPerPixelY - lHeight
        If (lTOp < 4 * Screen.TwipsPerPixelY) Then lTOp = 4 *
         Screen.TwipsPerPixelY
        If (lTOp + lHeight > Screen.Height - 4 * Screen.TwipsPerPixelY) Then
            lHeight = Screen.Height - lTOp - 4 * Screen.TwipsPerPixelY
        End If
    End If
    If (lWidth >= lMinWidth) And (lHeight >= lMinHeight) Then
        frmThis.Move lLeft, lTOp, lWidth, lHeight
    End If
    Key = "Maximised"
    If (CLngDefault(Value, 0) <> 0) Then
        frmThis.WindowState = vbMaximized
    End If
    Key = sSaveKey
    Default = sSaveDefault
    Exit Sub
LoadError:
    Key = sSaveKey
    Default = sSaveDefault
    m_lLastReturnCode = 0
    Exit Sub
End Sub
Public Function CLngDefault(ByVal sString As String, Optional ByVal lDefault As
 Long = 0) As Long
Dim lR As Long
On Error Resume Next
    lR = CLng(sString)
    If (Err.Number <> 0) Then
        CLngDefault = lDefault
    Else
        CLngDefault = lR
    End If
End Function



3> MarkJ..:

很多人会向您推荐XML.问题是XML仍然是如此时髦,有些人在没有真正考虑它的情况下到处使用它.

像杰夫阿特伍德说,这是很难的非程序员阅读XML,特别对其进行编辑.有太多规则,例如转义特殊字符并按正确顺序关闭标记.一些专家建议您将XML视为二进制格式,而不是文本格式.

我建议使用INI文件,前提是最大大小限制为32K不是问题.在我自己的VB6中,我在许多类似情况下从未达到过这个限制.INI文件很容易被普通民众编辑,并且很容易从VB6读取和写入.只需使用网上免费提供的一些优秀的插入代码即可.

我敢肯定,班杰里格斯在他的回答中提供非常出色,因为它是VBAccelerator.

我也推荐这门课,因为Karl Peterson的任何作品都会很棒.

还有几点需要考虑:

您是否考虑过将文件放入哪个目录?

你在问题中提到了"Unicode友好".INI文件不是Unicode,但在实践中并不重要.除非你想存储当前代码页不支持的字符 - 比如英文计算机上的中文字符 - 这是一个不寻常的要求,并且无论如何都会导致VB6程序中的其他问题.

传奇的Windows大师Raymond Chen描述了XML配置文件优于INI文件的优势.他们中的许多人依赖于只读的XML文件.一个合法的优势是,如果数据是高度结构化的 - 类层次结构等.根据您的描述不适用.

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有