0

I would like to ask for your help regarding my problem. I want to create a module for my program where it would read .txt file, find a specific value and insert it to the text box.

As an example I have a text file called system.txt which contains single line text. The text is something like this:

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

What i want to do is to get only the last name value "xxx_xxx" which every time can be different and insert it to my form's text box

Im totally new in programming, was looking for the other examples but couldnt find anything what would fit exactly to my situation.

Here is what i could write so far but i dont have any idea if there is any logic in my code:

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

Im

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • I'm sure right now the compiler has no idea what to make of the file name. At very least, put quotes around the it to get a string value. Also, for methods like this it's better to accept something like a file name as an input, and then return the results as a Function, rather than a Sub dumping into a shared variable. – Joel Coehoorn Dec 07 '20 at 18:58

5 Answers5

2

You can get this down to a function with a single line of code:

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

But for readability/maintainability and to avoid repeating the expression evaluation on each line I'd spread it out a bit:

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

See a simple example of the expression here:

https://dotnetfiddle.net/gJf3su

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
1

You can easily split that line in an array of strings using as separators the [ and ] brackets and removing any empty string from the result.

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)

At this point you have an array of strings and you can loop over it to find the entry that starts with the last name key, when you find it you can split at the = character and get the second element of the array

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

Of course, if you are sure that the second entry in each line is the Last Name entry then you can remove the loop and go directly for the entry

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

A more sophisticated way to remove the for each loop with a single line is using some of the IEnumerable extensions available in the Linq namespace.

So, for example, the loop above could be replaced with

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

As you can see, it is a lot more obscure and probably not a good way to do it anyway because there is no check on the eventuality that if the Last Name key is missing in the input string

Steve
  • 213,761
  • 22
  • 232
  • 286
1
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()
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
senthilkumar2185
  • 2,536
  • 3
  • 22
  • 36
1

Using your sample data...

I read the file and trim off the first and last bracket symbol. The small c following the the 2 strings tell the compiler that this is a Char. The braces enclosed an array of Char which is what the Trim method expects.

Next we split the file text into an array of strings with the .Split method. We need to use the overload that accepts a String. Although the docs show Split(String, StringSplitOptions), I could only get it to work with a string array with a single element. Split(String(), StringSplitOptions)

Then I looped through the string array called splits, checking for and element that starts with "Last Name=". As soon as we find it we return a substring that starts at position 10 (starts at zero).

If no match is found, an empty string is returned.

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

Usage...

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    TextBox1.Text = readcrnFile()
End Sub
Mary
  • 14,926
  • 3
  • 18
  • 27
  • 1
    Mary, you could get rid of the `Trim()` call on the end of the first line. Then change `{"]["}` to `"][".ToCharArray()`. This way it won't read the whole file as a string, then immediately create another entirely new string with just the square brackets removed on the ends. If the file is small it won't matter, but it was bugging me... =) – Idle_Mind Dec 07 '20 at 20:15
  • 1
    @Idle_Mind Thank you for the correction. I tried it and it worked. However, when I `Debug.Print` the contents of `splits` shows white space between the elements. Of course I can correct this with `StringSplitOptions.RemoveEmptyEntries`. It makes me think that the Char array is looking for 2 separate characters and the String is looking for the entire string. I tried to wade through the Reference Source but I am not too good at C#. – Mary Dec 08 '20 at 22:10
0

You should first know the difference between ReadAllLines() and ReadLines().

Then, here's an example using only two simple string manipulation functions, String.IndexOf() and 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
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40