How to populate a dimensioned Array Structure by a tab separated flat file

AB is a Structure with 15 fields ReDim(1)

Is there a smart way to populate AB unbound by a flat tab-separated file in a way that fields are populated in the same sequence as the fields are defined in the Structure definition, and assuming that the field order in the file is the same

It is also assumed that number of fields per record in the file is not greater than number of fields in the Structure definition, but it may be smaller.

It is also assumed that each file field contents may be converted to the DataType defined in the Structure definition.

The current solution is Redimensioning AB to a big safe number, reading each flat record into a grid control and then populate AB field by field, and then make a ReDim Preserve.  It works, but is rather slow with a great number of records.

Thanks.





 


Answer this question

How to populate a dimensioned Array Structure by a tab separated flat file

  • LogicMagic

    The is definiately a "more .NET way" of reading the file.  The .NET framework introduced FileStreams as an alternative to the FileOpen, FileClose, FreeFile, etc methods used in VB6.  Additionally there are classes such as the StreamReader and StreamWriter (in the IO namespace) that make reading files much easier.  Search MSDN for one of those classes if you wnat to learn more about the ".NET way" of dealing with files.

    As far as your actual question, I am assuming that StructureN is an array of some structure defined elsewhere.  There is in .NET a set of classes in the System.Collections namespace that make dynamic arrays simple.  When combined with the new Generics in .NET 2.0, they can answer this question quite nicely.  So enough talk, here's some code to answer your question:



    Public Function GetRecordsFromFile(ByVal fileName As String) As Record()
            Dim inputRecords As New List(Of Record)
            Dim rec As Record
            Dim line As String
            Dim fields() As String

            Using sr As New IO.StreamReader(fileName)
                While Not sr.EndOfStream
                    line = sr.ReadLine
                    fields = line.Split(Convert.ToChar(9))

                    rec = New Record(fields)
                    inputRecords.Add(rec)
                End While
            End Using

            Return inputRecords.ToArray
        End Function

    Public Class Record
            Public Sub New(ByVal fields() As String)
                Me.PopulateFromStrings(fields)
            End Sub

            Public Field1 As Integer
            Public Field2 As String
            'more fields here

            Public Sub PopulateFromStrings(ByVal fields() As String)
                If fields Is Nothing Then Throw New ArgumentNullException("fields")
                If fields.Length < Number_Of_Fields_In_Class Then
                    'either throw ArgumentException or resize array to be
                    'right size with default values
                End If

                Me.Field1 = Integer.Parse(fields(0))
                Me.Field2 = fields(1)
            End Sub
        End Class

     


  • Jon Jacobs

    It seems that this question is either very easy, very difficult or irrelevant, so I better try answering it myself after some tests.

    On MSDN, the differences and similarities between Class and Structure are described in a fine way.

    If one decides for Structure and Tab-delimited flat text files I think the answer is:

    Populate a dimensioned Structure using the Split method. It is very much faster than populating a grid first anyway.

    Dim Lin1, Lin2() as String
    Dim indx, f as Integer

    ReDim StructureN(aSafeNumber)
    indx = 1

    Open the file, read and populate like this:

    f = FreeFile
    FileOpen(f, "InputFile", OpenMode.Input)
    Do While Not EOF(f)
     Lin1 = LineInput(f)
     Lin2 = Lin1.Split(Chr(9))
     With StructureN(indx)
       .Field1 = CInt(Val(Lin2(0))) 'if an Integer in the Structure
       .Field2 = Lin2(1) ' if a String in the Structure
       ' etc 
     End With
     indx +=1
    Loop
    FileClose(f)
    'Perhaps a Redim Preserve here

    There may be a more .Net true way of reading the file.
    The risk is if some file record does not contain the expected number of fields. If this is considered to be a risk because someone else made the file, one may validate number of Tabs in Lin1.
    One may also validate indx while reading and make a Redim Preserve if number of records is greater than the maximum expected, but it takes time.





  • Greg Eisenberg

    Thanks, this must clearly be the right way of doing it in the .Net environment.

    For me there is much to learn from this code. I don't know if others find it simple, but it is definitely a new way of thinking for an old VB6 guy. Believe me, I'm reading MSDN, but I often find it difficult to find the right help text because I'm asking the wrong question.


  • How to populate a dimensioned Array Structure by a tab separated flat file