Home > Software engineering >  vb.net Read using reader, return data based on regex match and put that into data structure
vb.net Read using reader, return data based on regex match and put that into data structure

Time:07-23

I am trying to return all of the read data into an efficient data structure. The reader is doing it's job and returning the correct values from my regex. Now I am trying to store that data in memory and parse later. I want to do this in one button click event.

Sub ReadFile()
        Dim mapping As New Mapping()
        Dim variable As New MappingVariable()
        Dim P, line, startPosition, totalLength, id, name, number As String
        Dim m As Match
        Dim reader As New StreamReader("..\..\..\FileName.myp", System.Text.Encoding.Default)
        Do
            line = reader.ReadLine
            If line Is Nothing Then Continue Do
            m = Regex.Match(line, "^\[(\w )\]")
            P = m.Groups(1).ToString()
            mapping.P = P
            ' Grab that code
            If m.Groups.Count > 1 Then
                ' Read the next line after the code and get the 4 digits
                line = reader.ReadLine
                m = Regex.Match(line, "ID=\w\w(\w\w\w\w)")
                id = m.Groups(1).ToString()
                mapping.id = ID
                ' Then keep reading until the next blank line
                Do
                    line = reader.ReadLine
                    If line Is Nothing Then Continue Do
                    m = Regex.Match(line, ".*?(\d ),(\d ).*?\""(. ?)\"".*?(\d ) .*")
                    If m.Groups.Count > 1 Then
                        startPosition = m.Groups(1).ToString()
                        variable.startPosition = startPosition
                        totalLength = m.Groups(2).ToString()
                        variable.totalLength = totalLength
                        name = m.Groups(3).ToString()
                        variable.name = Name
                        number = m.Groups(4).ToString()
                        variable.number = number
                    End If
                Loop Until line = ""
            End If
        Loop Until line Is Nothing
        Console.WriteLine($"{mapping.p} - P")
        Console.WriteLine($"{mapping.id} - ID")
        For Each variables As MappingVariable In mapping.Variables
            Console.WriteLine($"{variable.startPosition} - startPosition")
            Console.WriteLine($"{variable.totalLength} - totalLength")
            Console.WriteLine($"{variable.name} - name")
            Console.WriteLine($"{variable.number} - number")
        reader.Close()
    End Sub

Button Function:

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

'New code to return a mapping object in order to write the desired output.
        Dim Test As New List(Of Mapping)

'The code used to call the reader
        Dim Testing = New ReadFile
        Testing.WriteToTempFile()
End Sub

CodePudding user response:

It's not clear from your question what exactly you're trying to do, but my guess is that you want to turn this into a function which returns all the data that was read from the file, in some kind of meaningful and easily readable data structure. I haven't tested it, but the algorithm for reading the data out of the file and parsing it with regex looks right, so if you say that part of it is working, I believe you. The problem is that you seem to be having trouble with how to store the data as objects in memory.

The first step is to design a class which declares the structure the data is going to take in memory. What that should look like will depend on your needs, and I don't know what those are, so I'll make some assumptions. Hopefully my example will be useful in at least giving you a starting point.

The following class can be used to hold the data from each Var= line:

Public Class MappingVariable
    Public Property StartPosition As String
    Public Property TotalLength As String
    Public Property Name As String
    Public Property Number As String
End Class

And the following class can be used to store the whole mapping (note that it includes the Variables property which is typed as a list of our MappingVariable class):

Public Class Mapping
    Public Property P As String
    Public Property Id As String
    Public Property Variables As New List(Of MappingVariable)()
End Class

Now, in the code, you can start by creating a Mapping object and filling it in with the header data that was read (before it starts reading the Var= lines):

Dim mapping As New Mapping()
mapping.P = p
mapping.Id = id

Then, after reading the data from each Var= line, you can create a MappingVariable object and add it to the mapping's Variables list:

Dim variable As New MappingVariable()
variable.StartPosition = startPosition
variable.TotalLength = totalLength 
variable.Name = name 
variable.Number = number 
mapping.Variables.Add(variable)

It's not clear whether the file contains multiple mappings or just one. If it contains just one, you could have the function return a Mapping object. If it can contain multiple, you could add them to a list after populating them and then have the function return a List(Of Mapping) object.

In any case, once you have the Mapping object, you can write the desired output from it like this:

Console.WriteLine($"{mapping.P} - P")
Console.WriteLine($"{mapping.Id} - ID")
For Each(variable As MappingVariable in mapping.Variables)
    Console.WriteLine($"{variable.StartPosition} - startPosition")
    Console.WriteLine($"{variable.TotalLength} - totalLength")
    Console.WriteLine($"{variable.Name} - name")
    Console.WriteLine($"{variable.Number} - number")
Next

There's all sorts of improvements that could be made to that, of course. You probably ought to have at least the position and length properties be typed as integers rather than strings, for instance. You may also want the variables stored in a dictionary, keyed by their name, number, or position for quicker access. But hopefully that's enough to get you pointed in the right direction.

Update

You're getting there, but you have things in the wrong place. Allow me to revise your code:

Function ReadFile() As List(Of Mapping)  ' Note that I changed this to a function and I have it returning a list of mappings
    Dim mappings As New List(Of Mapping)()
    Dim P, line, startPosition, totalLength, id, name, number As String
    Dim m As Match
    Dim reader As New StreamReader("..\..\..\FileName.myp", System.Text.Encoding.Default)
    Do
        Dim mapping As New Mapping()  ' Create a new mapping object for each one in the file rather than only creating it once at the top of the function
        line = reader.ReadLine
        If line Is Nothing Then Continue Do
        m = Regex.Match(line, "^\[(\w )\]")
        P = m.Groups(1).ToString()
        mapping.P = P
        ' Grab that code
        If m.Groups.Count > 1 Then
            ' Read the next line after the code and get the 4 digits
            line = reader.ReadLine
            m = Regex.Match(line, "ID=\w\w(\w\w\w\w)")
            id = m.Groups(1).ToString()
            mapping.id = ID
            ' Then keep reading until the next blank line
            Do
                line = reader.ReadLine
                If line Is Nothing Then Continue Do
                m = Regex.Match(line, ".*?(\d ),(\d ).*?\""(. ?)\"".*?(\d ) .*")
                If m.Groups.Count > 1 Then
                    Dim variable As New MappingVariable()  ' Create a new variable object for each Var= line rather than just creating one at the top of the function
                    startPosition = m.Groups(1).ToString()
                    variable.startPosition = startPosition
                    totalLength = m.Groups(2).ToString()
                    variable.totalLength = totalLength
                    name = m.Groups(3).ToString()
                    variable.name = Name
                    number = m.Groups(4).ToString()
                    variable.number = number
                    mapping.Variables.Add(variable)  ' Add this populated variable to this mapping's list of variables
                End If
            Loop Until line = ""
            mappings.Add(mapping)  ' Add this populated mapping to the list
        End If
    Loop Until line Is Nothing
    reader.Close()
    Return mappings  ' Return the list of mappings that were read from the file back to whatever was calling this function
End Function


Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim mappings As List(Of Mapping) = ReadFile()
    For Each mapping As Mapping in mappings
        Console.WriteLine($"{mapping.p} - P")
        Console.WriteLine($"{mapping.id} - ID")
        For Each variables As MappingVariable In mapping.Variables
            Console.WriteLine($"{variable.startPosition} - startPosition")
            Console.WriteLine($"{variable.totalLength} - totalLength")
            Console.WriteLine($"{variable.name} - name")
            Console.WriteLine($"{variable.number} - number")
        Next
    Next
End Sub
  • Related