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