阅读 .ini 文件 vb.net?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31402503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 09:40:52  来源:igfitidea点击:

Read .ini file vb.net?

.netvb.netwinapiini

提问by Andre Pabertiyan

I have one project with function to read .ini files. I can not display the contents of .ini file that I want to.

我有一个具有读取 .ini 文件功能的项目。我无法显示我想要的 .ini 文件的内容。

My code to read .ini file

我读取 .ini 文件的代码

Public Function GetSettingItem(ByVal File As String, ByVal Identifier As String) As String
    Dim S As New IO.StreamReader(File) : Dim Result As String = ""
    Do While (S.Peek <> -1)
        Dim Line As String = S.ReadLine
        If Line.ToLower.StartsWith(Identifier.ToLower & "=") Then
            Result = Line.Substring(Identifier.Length + 2)
        End If
    Loop
    Return Result
End Function

My code to load code

我的代码加载代码

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Label1.Text = GetSettingItem("D:\WorldInfo.ini", "Count")
    Label2.Text = GetSettingItem("D:\WorldInfo.ini", "Count")
 End Sub

my .ini files

我的 .ini 文件

[B_Empty_IndexList]
Count=2
00_Th=0
01_Th=1
[B_Use_IndexList]
Count=0
00_Th=-1
01_Th=-1

in my project i wanna load information Count from [B_Empty_IndexList] to Label1 and Count from [B_Use_IndexList] to Label2 .. but when i use my code Label1 and Label2 just load Count from [B_Use_IndexList]

在我的项目中,我想将信息 Count 从 [B_Empty_IndexList] 加载到 Label1 并将信息从 [B_Use_IndexList] 加载到 Label2 ..但是当我使用我的代码 Label1 和 Label2 时,只需从 [B_Use_IndexList] 加载 Count

Anyone help me how to read ini file to load information

任何人都可以帮助我如何读取ini文件以加载信息

Label1 -> Load Information Count from [B_Empty_IndexList]
Label2 -> Load Information Count from [B_Use_IndecList]

Sorry for my bad english

对不起,我的英语不好

回答by Matt Wilko

There is no point rolling your own method to do this. Use the Windows API method GetPrivateProfileString to do it:

没有必要滚动你自己的方法来做到这一点。使用 Windows API 方法 GetPrivateProfileString 来做到这一点:

Imports System.Runtime.InteropServices
Imports System.Text

<DllImport("kernel32")>
Private Shared Function GetPrivateProfileString(ByVal section As String, ByVal key As String, ByVal def As String, ByVal retVal As StringBuilder, ByVal size As Integer, ByVal filePath As String) As Integer
End Function

Public Function GetIniValue(section As String, key As String, filename As String, Optional defaultValue As String = "") As String
    Dim sb As New StringBuilder(500)
    If GetPrivateProfileString(section, key, defaultValue, sb, sb.Capacity, filename) > 0 Then
        Return sb.ToString
    Else
        Return defaultValue
    End If
End Function

Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
    Debug.WriteLine(GetIniValue("B_Empty_IndexList", "Count", My.Application.Info.DirectoryPath & "\WorldInfo.ini"))
    Debug.WriteLine(GetIniValue("B_Use_IndexList", "Count", My.Application.Info.DirectoryPath & "\WorldInfo.ini"))
End Sub

Note some background reading if using this approach: Could there be encoding-related problems when storing unicode strings in ini files?

如果使用这种方法,请注意一些背景阅读:在 ini 文件中存储 unicode 字符串时是否存在与编码相关的问题?

回答by Mario Z

Those suggested Windows API have been deprecated for a long time now and they are really bad, you see on each GetPrivateProfile call you are reading and parsing the INI content all over again...

那些建议的 Windows API 现在已经被弃用了很长时间,它们真的很糟糕,你在每个 GetPrivateProfile 调用中看到你正在重新阅读和解析 INI 内容......

As an alternative try using my MadMilkman.Ini library, like this:

作为替代尝试使用我的 MadMilkman.Ini 库,如下所示:

Imports MadMilkman.Ini

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim ini As New IniFile()
    ini.Load("D:\WorldInfo.ini")

    Label1.Text = ini.Sections("B_Empty_IndexList").Keys("Count").Value
    Label2.Text = ini.Sections("B_Use_IndecList").Keys("Count").Value
End Sub

You can download the library from here: https://github.com/MarioZ/MadMilkman.Ini

你可以从这里下载库:https: //github.com/MarioZ/MadMilkman.Ini

EDIT
I was asked to elaborate more the discussion that I had with IInspectable in the comments below.
IInspectable: "Your solution doesn't appear to account for surrogate pairs."
Mario Z: "I have no idea why you assume that library doesn't support Unicode, it does and its quite simple... just use the appropriate encoding."

编辑
我被要求在下面的评论中详细说明我与 IInspectable 的讨论。
IInspectable:“您的解决方案似乎没有考虑代理对。”
Mario Z:“我不知道你为什么认为该库不支持 Unicode,它确实支持,而且非常简单……只需使用适当的编码即可。”

So here it goes, in short .NET's String represents an array of Chars and Char represents 16-bit character. When faced with a string that contains a 32-bit character it will use a so called "surrogate pair" (two characters that represent one). Now when working with this kind of string an issue that can happen for example is that we can make an invalid substring of that string if we cut it in the middle of that "surrogate pair". Also another issue that can happen is when working with the string indexer and not taking into account that a "surrogate pair" will consist of two indexed chars in that string.

就这样吧,简而言之,.NET 的 String 代表一个 Chars 数组,而 Char 代表 16 位字符。当遇到包含 32 位字符的字符串时,它将使用所谓的“代理对”(两个字符代表一个)。现在,当使用这种字符串时,可能会发生的一个问题是,如果我们在“代理对”的中间剪切它,我们可以创建该字符串的无效子字符串。另一个可能发生的问题是在使用字符串索引器时没有考虑到“代理对”将由该字符串中的两个索引字符组成。

However that is all not the case with MadMilkman.Ini, the library directly manipulates only with a specific set of characters while the rest of the string is left as it is (string is a self-consistent type with a full Unicode support). The characters that are targeted and manipulated are [, ], =, etc.

然而,MadMilkman.Ini 并非如此,该库仅直接使用一组特定的字符进行操作,而字符串的其余部分保持原样(字符串是具有完整 Unicode 支持的自洽类型)。被定位和操纵的字符是 [、]、= 等。

As an example here is a writing test sample:

作为一个例子,这里是一个写作测试样本:

Dim textWithSurrogatePairs =
    "sample content " + Char.ConvertFromUtf32(Int32.Parse("22222", NumberStyles.HexNumber))

Dim ini = New IniFile(
    New IniOptions() With {.Encoding = Encoding.Unicode})

ini.Sections.Add(
    New IniSection(ini, "sample section",
        New IniKey(ini, "sample key", textWithSurrogatePairs)))

ini.Save("sample file.ini")

The following is the content of "textWithSurrogatePairs" variable:

以下是“textWithSurrogatePairs”变量的内容:

enter image description here

在此处输入图片说明

The following is the generated output "sample file.ini" file:

以下是生成的输出“sample file.ini”文件:

enter image description here

在此处输入图片说明

Also here is reading test sample:

这里也是阅读测试样本:

Dim ini = New IniFile(
    New IniOptions() With {.Encoding = Encoding.Unicode})

ini.Load("sample file.ini")

Dim readValue = ini.Sections("sample section").Keys("sample key").Value

The following is the "readValue" variable:

以下是“readValue”变量:

enter image description here

在此处输入图片说明

So in short the .NET framework itself handles the surrogate pairs, the only thing that we need to be aware of is to use an appropriate Encoding (as shown above).
Unfortunately this is something that IInspectable fails to realize and I failed to properly explain to him.

所以简而言之,.NET 框架本身处理代理对,我们唯一需要注意的是使用适当的编码(如上所示)。
不幸的是,这是 IInspectable 没有意识到的事情,我也没有向他正确解释。

回答by Daniel Gee

Example ini file:

示例 ini 文件:

[MAIN]
Setting_1=something

a. Create a class clsINI

一种。创建类 clsINI

Public Class clsIni
' API functions
Private Declare Ansi Function GetPrivateProfileString _
  Lib "kernel32.dll" Alias "GetPrivateProfileStringA" _
  (ByVal lpApplicationName As String, _
  ByVal lpKeyName As String, ByVal lpDefault As String, _
  ByVal lpReturnedString As System.Text.StringBuilder, _
  ByVal nSize As Integer, ByVal lpFileName As String) _
  As Integer
Private Declare Ansi Function WritePrivateProfileString _
  Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
  (ByVal lpApplicationName As String, _
  ByVal lpKeyName As String, ByVal lpString As String, _
  ByVal lpFileName As String) As Integer
Private Declare Ansi Function GetPrivateProfileInt _
  Lib "kernel32.dll" Alias "GetPrivateProfileIntA" _
  (ByVal lpApplicationName As String, _
  ByVal lpKeyName As String, ByVal nDefault As Integer, _
  ByVal lpFileName As String) As Integer
Private Declare Ansi Function FlushPrivateProfileString _
  Lib "kernel32.dll" Alias "WritePrivateProfileStringA" _
  (ByVal lpApplicationName As Integer, _
  ByVal lpKeyName As Integer, ByVal lpString As Integer, _
  ByVal lpFileName As String) As Integer
Dim strFilename As String

' Constructor, accepting a filename
Public Sub New(ByVal Filename As String)
    strFilename = Filename
End Sub

' Read-only filename property
ReadOnly Property FileName() As String
    Get
        Return strFilename
    End Get
End Property

Public Function GetString(ByVal Section As String, _
  ByVal Key As String, ByVal [Default] As String) As String
    ' Returns a string from your INI file
    Dim intCharCount As Integer
    Dim objResult As New System.Text.StringBuilder(256)
    intCharCount = GetPrivateProfileString(Section, Key, [Default], objResult, objResult.Capacity, strFilename)
    If intCharCount > 0 Then
        GetString = Left(objResult.ToString, intCharCount)
    Else
        GetString = ""
    End If

End Function

Public Function GetInteger(ByVal Section As String, _
  ByVal Key As String, ByVal [Default] As Integer) As Integer
    ' Returns an integer from your INI file
    Return GetPrivateProfileInt(Section, Key, _
       [Default], strFilename)
End Function

Public Function GetBoolean(ByVal Section As String, _
  ByVal Key As String, ByVal [Default] As Boolean) As Boolean
    ' Returns a boolean from your INI file
    Return (GetPrivateProfileInt(Section, Key, _
       CInt([Default]), strFilename) = 1)
End Function

Public Sub WriteString(ByVal Section As String, _
  ByVal Key As String, ByVal Value As String)
    ' Writes a string to your INI file
    WritePrivateProfileString(Section, Key, Value, strFilename)
    Flush()
End Sub

Public Sub WriteInteger(ByVal Section As String, _
  ByVal Key As String, ByVal Value As Integer)
    ' Writes an integer to your INI file
    WriteString(Section, Key, CStr(Value))
    Flush()
End Sub

Public Sub WriteBoolean(ByVal Section As String, _
  ByVal Key As String, ByVal Value As Boolean)
    ' Writes a boolean to your INI file
    WriteString(Section, Key, CStr(CInt(Value)))
    Flush()
End Sub

Private Sub Flush()
    ' Stores all the cached changes to your INI file
    FlushPrivateProfileString(0, 0, 0, strFilename)
End Sub
End Class

b. Instantiate the class:

湾 实例化类:

Dim objIniFile As New clsIni(path_of_your_file)

c. Get the setting:

C。获取设置:

Dim x As String
x = objIniFile.GetString("MAIN", "Setting_1", "")

d. Update / Create a setting:

d. 更新/创建设置:

objIniFile.WriteString("MAIN", "Setting_1", "new_setting")

Edit:

编辑:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim objIniFile As New clsIni("D:\WorldInfo.ini")
    Label1.Text = objIniFile.GetString("B_Empty_IndexList", "Count", "")
    Label2.Text = objIniFile.GetString("B_Use_IndexList", "Count", "")
End Sub