Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populate large class from fixed width data

Tags:

c#

I have a class with a large number of properties, example:

class MyStudent {
    public string NAME;
    public string TUTOR;
    public int AGE;
    // ... 100+ items
}

The data is read from a fixed width text file:

Matt    John    20
JonathonBob     22

The data file is defined in a separate xref file:

NAME    8
TUTOR   8
AGE     2

I want to populate my class from each line of data then add it to a list of this type. This is the method I am using, can it be made more efficient (without changing the input data files)?

Firstly I've read the xref file into a list so I can access the WIDTH field using LINQ.

/* Read File */
List<MyStudent> signal_file = new List<MyStudent>();
while ((_dba_line = _dba_file.ReadLine()) != null)
{
    if (!_dba_line.Substring(0, 2).Equals("--")) // Not a comment
    {
        MyStudent temp_signal = new MyStudent();
        int _offset = 0;
        int _width = 0;

        _width = xref_file.First(item => item.DBU_FIELD == "NAME").WIDTH;
        temp_signal.NAME = _dba_line.Substring(_offset, _width).Trim();
        _offset += _width;

        _width = xref_file.First(item => item.DBU_FIELD == "TUTOR").WIDTH;
        temp_signal.TUTOR = _dba_line.Substring(_offset, _width).Trim();
        _offset += _width;

        // Continue for each property
        // ...

        // Finally
        signal_file.Add(temp_signal);
    }
}

I think the key may be that the xref DBU_FIELD always equals the property name in the class and is in the correct order to match the line of data. What I would like to achieve if possible would be closer to:

foreach (XrefObject x in xref_file)
{
    _width = x.WIDTH;
    temp_signal.(x.DBU_FIELD) = _dba_line.Substring(_offset, _width).Trim();
    _offset += _width;
}

// Finally
signal_file.Add(temp_signal);

It's how to use the xref object DBU_FIELD value to access the student object associated property I am unsure of (if possible).

For info in this use the files have been validated prior to use so they are guaranteed to match up correctly.

I am open to create as a struct rather than an object if that makes more sense, there are typically 500 instances each with approx 100 fields of mixed string, int and float.

I am also looking for the best practice way to handle this type of data structure, not just force it to work.

like image 934
MattP Avatar asked May 11 '26 01:05

MattP


1 Answers

You can use Reflection's GetProperty and SetValue methods

using System.Reflection;        

foreach (XrefObject x in xref_file)
{
    _width = x.WIDTH;

    PropertyInfo prop = 
        temp_signal.GetType()
            .GetProperty(x.DBU_FIELD, BindingFlags.Public | BindingFlags.Instance);

    if(prop != null && prop.CanWrite)
    {
        prop.SetValue(temp_signal, _dba_line.Substring(_offset, _width).Trim(), null);
    }

    _offset += _width;
}
like image 165
tafa Avatar answered May 12 '26 15:05

tafa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!