JKirkbride
JKirkbride

Reputation: 110

Deserialize list of objects from a file to be displayed

Basically I have created a file that I store serialized data from an Object called TravelRecord. I have no issue serializing the data and storing it in the file using a BinaryFormatter(), and I have no issue retrieving the first record. I just want to retrieve all the records and display them in a ListBox.

Here's some of the relevant code:

     Private reader As New BinaryFormatter()
     Private input As FileStream
     input = New FileStream(fileName, FileMode.Open, FileAccess.Read)

     Dim record = CType(reader.Deserialize(input), TravelRecord)
     RequestLst.items.Add(record.toString())

This works for returning the first record, but I want it to return all of them so I can iterate through them like the following:

 For Each r As TravelRecord In records
            RequestLst.Items.Add(r.ToString())
        Next

I know I'm probably missing something really simple, but everything I try causes RunTime errors. There may also be a better way to handle this.

Here is what the serialized data in the file looks like.

  ÿÿÿÿ          DTravelRequest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   TravelRequest.TravelRecord   ID FirstNameLastNamePurpose    StartDateEndDateAmount   System.Guid

   ýÿÿÿSystem.Guid   _a_b_c_d_e_f_g_h_i_j_k           “ŸPªO½cùømFÚw   Steve   Robinson   Semianr  U¾Ó €æ©PÓ     @o@ @_@    ÿÿÿÿ          DTravelRequest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   TravelRequest.TravelRecord   ID    FirstNameLastNamePurpose    StartDateEndDateAmount   System.Guid

   ýÿÿÿSystem.Guid   _a_b_c_d_e_f_g_h_i_j_k           æ;o˜ùéAÎÜ^pñÌ   jake      Kirkbride   Stuff  l«™  Ó €CøX,Ô     À^@    ÿÿÿÿ          DTravelRequest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   TravelRequest.TravelRecord   ID   FirstNameLastNamePurpose    StartDateEndDateAmount   System.Guid

   ýÿÿÿSystem.Guid   _a_b_c_d_e_f_g_h_i_j_k           FP“¼Î«Gž¥5tuUš   steve    stevenson   vacation @áw%Ó @ˆ!?(Ó     @_@    ÿÿÿÿ          DTravelRequest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   TravelRequest.TravelRecord   ID  FirstNameLastNamePurpose    StartDateEndDateAmount   System.Guid

   ýÿÿÿSystem.Guid   _a_b_c_d_e_f_g_h_i_j_k           ‹MÆoh#D–âÑQþ…P   Steve    Stevenson   Program €œN4)Ô €CøX,Ô     @_@    ÿÿÿÿ          DTravelRequest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null   TravelRequest.TravelRecord   ID  FirstNameLastNamePurpose    StartDateEndDateAmount   System.Guid

   ýÿÿÿSystem.Guid   _a_b_c_d_e_f_g_h_i_j_k           k$ˆµ§FŠm§Íüâ   George    Govern   Stuff €CøX,Ô €ê¡}/Ô      `@

It seems my issue is how do I read all of these and turn them into a collection so I can work with them.

Here is the code for the TravelRecord Class:

    <Serializable()>
    Public Class TravelRecord

    'Class fields
    Public ID As Guid
    Public FirstName As String
    Public LastName As String
    Public Purpose As String
    Public StartDate As Date
    Public EndDate As Date
    Public Amount As Double

    Public Sub New()
        MyClass.New(Guid.Empty, String.Empty, String.Empty, String.Empty,
                    Nothing, Nothing, 0.0)
    End Sub

    Public Sub New(id As Guid, fName As String, lName As String,
                   purpose As String, startDate As Date, endDate As Date,
                   amount As Double)
        MyClass.ID = id
        MyClass.FirstName = fName
        MyClass.LastName = lName
        MyClass.Purpose = purpose
        MyClass.StartDate = startDate
        MyClass.EndDate = endDate
        MyClass.Amount = amount
    End Sub

    Public Overrides Function ToString() As String
        Return String.Format("{0,-40}{1,-10}{2,-10}{3,-15}{4,12:d}{5,12:d}{6,12:C}", _
            ID, FirstName, LastName, Purpose, StartDate, EndDate, Amount)
    End Function
End Class

From comments:

The serialization code:

formatter.Serialize(output, travelRequest) 

Where travelRequest is an instance of TravelRecord.

I might need to explain this better is all. The system is for a User to submit TravelRecords. The Serialization is setup to Append a new TravelRecord to the file to act as like a database. (This is a homework assignment I usually use SQL). The Deserialization is to read all of the entries in the File and display them in a summary ListBox.

The reason Deserialization is only getting one TravelRecord is because I don't know how to get all the TravelRecords out of the File.

Is there a way to get a count of how many items are in the serialized file so I can do a finite For loop or something

Upvotes: 1

Views: 728

Answers (1)

You write one record at a time:

formatter.Serialize(output, travelRequest)

so you will have to read back one record at a time. The BinaryFomratter stores Type data along with the data (TravelRecord) so you cant just read it back as a collection (array or List(of TravelRecord) because there is no way it can convert from one Type to a collection Type (without some gyrations I am sure you dont want to undertake). You can see the Type data in the file:

TravelRequest, Version=1.0.0.0, Culture=neutral, PublicKeyToken...

The file wont be random access, so to get record 3 or find "Foo" you will have to do something similar (eg test for username = "Bob" and Exit For). Standing in for TravelRecord is a class named NVP which I happen to have handy.

Function GetListofTravelRecords() As List(Of NVP)
    Dim tmpList As New List(Of NVP)
    Dim tmp As NVP

    Using fs As New FileStream("C:\Temp\nvplst.bin", FileMode.Open)
        Dim bf As New BinaryFormatter

        Do Until fs.Position >= fs.Length
            tmp = CType(bf.Deserialize(fs), NVP)
            tmpList.Add(tmp)
        Loop

    End Using
    Return tmpList

End Function

Usage and test:

Dim mylist = GetListofTravelRecords()

For Each item In mylist
    Console.WriteLine(item.ToString)
Next

Output:

ziggy (1)
zacky (2)
zoey (3)
ziggy (4)
zacky (5)

I had 11 things in there and they all made it back safely and in the same order.


Note to others, it is much easier to serialize an entire collection and read it back as collection.

Upvotes: 2

Related Questions