Question Spliting records into variable formats

rhoaste

Member
Joined
Jun 16, 2010
Messages
19
Programming Experience
10+
Hi

I am splitting data from an ASCII file generated by another system which has records of a varied format. The first 2 characters in each record are used to indicate the structure of the remaining data in the record. For example:

VB.NET:
         1         2         3         4         5
12345678901234567890123456789012345678901234567890
---------+---------+---------+---------+---------+
01Jane      Smith     12 Aintree Ave         2215
051515302Standard  12-01-2010
01Bob       Foster    3 Frond Street         2010
055655154Advanced  12-01-2010

In the data above, when the first 2 characters are "01" then the format of the remaining record is:
Name (10)
Surname (10)
AddressLine1 (23)
Postcode (4)

When the first 2 characters are "05" then the format of the remaining record is:
AccountNo (7)
ServiceType (10)
StartDate(10)

The above data is very simple. In reality there are many types of records all of varing length and structure depending on the first 2 characters. I only really need to deal with the data as strings- so there's no numeric conversion required.

I had intended to do a giant Select Case statement in order strip out the appropriate parts of the record by substring depending on the first two characters value. However, I was wondering if there was a more maintainable / elegant approach. I was thinking perhaps something more along the lines of using various predefined data structures which map to each record type. I would then be able to read in the record as a string, determine the record type and populate the appropriate data structure in one fell swoop. I have done this kind of operation in other programming languages and wondered if something similar could be done in VB.NET. My investigations into deserializing strings to structures have not been successful.

I would be grateful for your ideas.

Kind regards.
 

rhoaste

Member
Joined
Jun 16, 2010
Messages
19
Programming Experience
10+
You should probably look at the TextFieldParser class. I think it can do all you need. Code examples in the doco.

Hi,

My objective is to make things easier to maintain and more elegant. Although I guess at a push it would be possible from what I've read about TextFieldParser, from my understanding of it's implementation, the required code would be unjustifiably complex for what I would like to achieve.

Regards.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
No it wouldn't. If you're looking for a one-liner then you're out of luck. What you want is not trivial so the code to do it wont be trivial but I don't see it as being outrageously complex. It's up to you whether you pursue it though.
 

JohnH

VB.NET Forum Moderator
Staff member
Joined
Dec 17, 2005
Messages
15,561
Location
Norway
Programming Experience
10+
Although I guess at a push it would be possible from what I've read about TextFieldParser, from my understanding of it's implementation, the required code would be unjustifiably complex for what I would like to achieve.
Then you must have been looking at the wrong place, because this is dead simple to achieve using TextFieldParser, you're basically looking at a call to PeekChars and SetFieldWidths methods in a loop:
        Using parser As New FileIO.TextFieldParser("data.txt")
            parser.TextFieldType = FileIO.FieldType.FixedWidth
            Do Until parser.EndOfData
                Dim condition = parser.PeekChars(2)
                If condition = "01" Then
                    parser.SetFieldWidths(2, 10, 10, 23, 4)
                ElseIf condition = "05" Then
                    parser.SetFieldWidths(2, 7, 10, 10)
                End If
                Dim fields = parser.ReadFields
                ' use fields
            Loop 
        End Using
 

rhoaste

Member
Joined
Jun 16, 2010
Messages
19
Programming Experience
10+
No it wouldn't. If you're looking for a one-liner then you're out of luck. What you want is not trivial so the code to do it wont be trivial but I don't see it as being outrageously complex. It's up to you whether you pursue it though.

No. I'm not looking for a "one-liner".
I'm looking for ideas on an alternative way to populate values directly into a data structure (or class) that is maintainable (avoiding obfuscation), whilst still being elegant and efficient.

Then you must have been looking at the wrong place, because this is dead simple to achieve using TextFieldParser, you're basically looking at a call to PeekChars and SetFieldWidths methods in a loop:
        Using parser As New FileIO.TextFieldParser("data.txt")
            parser.TextFieldType = FileIO.FieldType.FixedWidth
            Do Until parser.EndOfData
                Dim condition = parser.PeekChars(2)
                If condition = "01" Then
                    parser.SetFieldWidths(2, 10, 10, 23, 4)
                ElseIf condition = "05" Then
                    parser.SetFieldWidths(2, 7, 10, 10)
                End If
                Dim fields = parser.ReadFields
                ' use fields
            Loop 
        End Using

Yes, I WAS looking in the wrong place. Thank you very much for supplying the example code. I was rather hoping though to be able to load the parsed data directly into a data structure or class as opposed to an array.

Kind regards.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
I was rather hoping though to be able to load the parsed data directly into a data structure or class as opposed to an array.
You have no option but to read the data as a String array because that's how the TextFieldParser works. What you do with the data after that is up to you though. If you know beforehand what the possible data combinations are then you can define a class for each one. As you read the data you then create an instance of the appropriate type for each each record, parse the String fields you get from the TFP and populate the properties of your object. You would decide which type to use in the same way as you decide how to set the field widths.
 

rhoaste

Member
Joined
Jun 16, 2010
Messages
19
Programming Experience
10+
I guess reflection could be used, providing the data was stored in a class as opposed to a structure.

VB.NET:
Dim x As Integer = 0
Dim NameData As New NameClass
Dim fldinfo As FieldInfo() = NameData.GetType.GetFields
For Each item As FieldInfo In fldinfo
    item.SetValue(NameData, fields(x))
    x = x + 1
Next
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
Why would you need to use Reflection? You know that you have a NameClass object so you know what properties it has, so you just set them. I'd be inclined to write a method for each type that took a String array as an argument, created an instance of the appropriate type, parsed the Strings and set the properties and then returned the object.
 

rhoaste

Member
Joined
Jun 16, 2010
Messages
19
Programming Experience
10+
You're right. But I don't see any advantage over just cutting the strings directly out of the data read and placing them in the appropriate variables. I was hoping there'd be something in VB.NET that would allow me to map a record read from a file directly into predetermined formatted buffers of various formats.
 
Top Bottom