【问题标题】:Get a specific value from the line in brackets (Visual Studio 2019)从括号中的行获取特定值 (Visual Studio 2019)
【发布时间】:2021-03-18 23:08:07
【问题描述】:

我想就我的问题寻求您的帮助。我想为我的程序创建一个模块,它将读取 .txt 文件,找到一个特定的值并将其插入到文本框中。

例如,我有一个名为system.txt 的文本文件,其中包含单行文本。文字是这样的:

[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]

我想要做的是只获取每次都可以不同的姓氏值“xxx_xxx”并将其插入表单的文本框

我完全是编程新手,正在寻找其他示例,但找不到任何适合我的情况。

这是我到目前为止可以写的,但我不知道我的代码中是否有任何逻辑:

Dim field As New List(Of String)

Private Sub readcrnFile()
For Each line In File.ReadAllLines(C:\test\test_1\db\update\network\system.txt)
    For i = 1 To 3
        If line.Contains("Last Name=" & i) Then
            field.Add(line.Substring(line.IndexOf("=") + 2))
        End If
    Next
Next
End Sub

【问题讨论】:

  • 我确定现在编译器不知道文件名的含义。至少,在它周围加上引号以获得一个字符串值。此外,对于这样的方法,最好接受文件名之类的内容作为输入,然后将结果作为函数返回,而不是将 Sub 转储到共享变量中。

标签: vb.net


【解决方案1】:

您可以使用 [ 和 ] 括号作为分隔符轻松将该行拆分为字符串数组,并从结果中删除任何空字符串。

Dim input As String = "[Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim parts = input.Split(New Char() {"["c, "]"c}, StringSplitOptions.RemoveEmptyEntries)

此时你有一个字符串数组,你可以遍历它以找到以姓氏键开头的条目,当你找到它时,你可以在 = 字符处拆分并获取数组的第二个元素

For Each p As String In parts
    If p.StartsWith("Last Name") Then
        Dim data = p.Split("="c)
        field.Add(data(1))
        Exit For
    End If
Next

当然,如果您确定每行中的第二个条目是姓氏条目,那么您可以删除循环并直接进入条目

Dim data = parts(1).Split("="c)

使用单行删除 for each 循环的更复杂的方法是使用 Linq 命名空间中可用的一些 IEnumerable 扩展。

因此,例如,上面的循环可以替换为

field.Add((parts.FirstOrDefault(Function(x) x.StartsWith("Last Name"))).Split("="c)(1))

如您所见,它更加晦涩难懂,而且可能不是一个好方法,因为没有检查输入字符串中是否缺少姓氏键的可能性

【讨论】:

  • 我不知道
【解决方案2】:
Dim strval As String = " [Name=John][Last Name=xxx_xxx][Address=xxxx][Age=22][Phone Number=8454845]"
Dim strline() As String = strval.Split(New String() {"[", "]"}, StringSplitOptions.RemoveEmptyEntries) _
    .Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
    .ToArray()
Dim lastnameArray() = strline(1).Split("=")
Dim lastname = lastnameArray(1).ToString()

【讨论】:

  • String.Split 总是产生一个字符串数组,所以.ToString() 是多余的。
【解决方案3】:

你可以用一行代码把它归结为一个函数:

Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
    Return File.ReadLines(fileName).Where(Function(line) RegEx.IsMatch(line, "[[[]Last Name=(?<LastName>[^]]+)]").Select(Function(line) RegEx.Match(line, exp).Groups("LastName").Value)
End Function

但为了可读性/可维护性以及避免在每一行上重复表达式评估,我会将其展开一点:

Private Function readcrnFile(fileName As String) As IEnumerable(Of String)
    Dim exp As New RegEx("[[[]Last Name=(?<LastName>[^]]+)]")

    Return File.ReadLines(fileName).
        Select(Function(line) exp.Match(line)).
        Where(Function(m) m.Success).
        Select(Function(m) m.Groups("LastName").Value)
End Function

在此处查看表达式的简单示例:

https://dotnetfiddle.net/gJf3su

【讨论】:

    【解决方案4】:

    使用您的样本数据...

    我阅读了文件并删除了第一个和最后一个括号符号。两个字符串后面的小c 告诉编译器这是一个Char。大括号包含了一个 Char 数组,这是 Trim 方法所期望的。

    接下来,我们使用.Split 方法将文件文本拆分为字符串数组。我们需要使用接受String 的重载。尽管文档显示Split(String, StringSplitOptions),但我只能让它与具有单个元素的字符串数组一起使用。 Split(String(), StringSplitOptions)

    然后我循环遍历名为splits 的字符串数组,检查以"Last Name=" 开头的元素。一旦我们找到它,我们就会返回一个从位置 10(从零开始)开始的子字符串。

    如果没有找到匹配项,则返回一个空字符串。

    Private Function readcrnFile() As String
        Dim LineInput = File.ReadAllText("system.txt").Trim({"["c, "]"c})
        Dim splits = LineInput.Split({"]["}, StringSplitOptions.None)
        For Each s In splits
            If s.StartsWith("Last Name=") Then
                Return s.Substring(10)
            End If
        Next
        Return ""
    End Function
    

    用法...

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        TextBox1.Text = readcrnFile()
    End Sub
    

    【讨论】:

    • 玛丽,你可以去掉第一行末尾的Trim() 调用。然后将{"]["} 更改为"][".ToCharArray()。这样它就不会将整个文件作为字符串读取,然后立即创建另一个全新的字符串,只删除末端的方括号。如果文件很小,那没关系,但它困扰着我...... =)
    • @Idle_Mind 谢谢指正。我试过了,它奏效了。但是,当我Debug.Print splits 的内容显示元素之间的空白。当然我可以用StringSplitOptions.RemoveEmptyEntries 纠正这个问题。这让我觉得 Char 数组正在寻找 2 个单独的字符,而 String 正在寻找整个字符串。我试图浏览参考源,但我不太擅长 C#。
    【解决方案5】:

    你应该先知道difference between ReadAllLines() and ReadLines()

    然后,这是一个仅使用两个简单字符串操作函数的示例,String.IndexOf()String.Substring()

    Sub Main(args As String())
        Dim entryMarker As String = "[Last Name="
        Dim closingMarker As String = "]"
        Dim FileName As String = "C:\test\test_1\db\update\network\system.txt"
    
        Dim value As String = readcrnFile(entryMarker, closingMarker, FileName)
        If Not IsNothing(value) Then
            Console.WriteLine("value = " & value)
        Else
            Console.WriteLine("Entry not found")
        End If
    
        Console.Write("Press Enter to Quit...")
        Console.ReadKey()
    End Sub
    
    Private Function readcrnFile(ByVal entry As String, ByVal closingMarker As String, ByVal fileName As String) As String
        Dim entryIndex As Integer
        Dim closingIndex As Integer
        For Each line In File.ReadLines(fileName)
            entryIndex = line.IndexOf(entry) ' see if the marker is in our line
            If entryIndex <> -1 Then
                closingIndex = line.IndexOf(closingMarker, entryIndex + entry.Length) ' find first "]" AFTER our entry marker
                If closingIndex <> -1 Then
                    ' calculate the starting position and length of the value after the entry marker
                    Dim startAt As Integer = entryIndex + entry.Length
                    Dim length As Integer = closingIndex - startAt
                    Return line.Substring(startAt, length)
                End If
            End If
        Next
        Return Nothing
    End Function
    

    【讨论】:

      猜你喜欢
      • 2020-05-27
      • 2020-12-04
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-24
      • 2020-01-30
      相关资源
      最近更新 更多