Rueben.Ramirez Rueben.Ramirez - 6 months ago 23
Vb.net Question

Input stream is not a valid binary format.

in the following I am serializing the class object "ListViewCereal" into a memory stream and then storing the memory stream's buffer to an access database column.

If chkSerialize.Checked = True Then
Dim cereal As New ListViewCereal 'class used to store item list views
Dim bin_form As New BinaryFormatter 'used to serialize and deserialize objects
Dim file_stream As New MemoryStream 'serialization stream
Dim report_row As DataRow = mycallerPreview.previewInst.SerializedDataDataSet.SavedReportLayouts.NewRow

cereal.prep_cereal(MoveItemListViewClass1, MoveItemListViewClass2, MoveItemListViewClass3)
bin_form.Serialize(file_stream, cereal)
builder.Clear()

'extract buffer and append string representation of each bit to StringBuilder "builder"
file_stream.Position = 0
Dim byteArray() As Byte = file_stream.GetBuffer()
For Each bit As Byte In byteArray
builder.Append(bit.ToString)
Next

report_row("Serialized Data") = builder.ToString 'column storing string rep. of buffer

builder.Clear()
builder.Append(txtYear.Text.ToString).Append("-").Append(txtVendor.Text.ToString).Append("-").Append(txtReport.Text.ToString)
report_row("Report Name") = builder.ToString
report_row("User Name") = "" 'TODO:setup login window to track users
mycallerPreview.previewInst.SerializedDataDataSet.SavedReportLayouts.AddSavedReportLayoutsRow(report_row)
mycallerPreview.previewInst.TableAdapterManager.UpdateAll(mycallerPreview.previewInst.SerializedDataDataSet)

file_stream.Close()
file_stream.Dispose()
mycallerPreview.Show()
mycallerPreview.previewInst.Close()
mycallerPreview.previewInst = Nothing
Else
mycallerPreview.Show()
mycallerPreview.previewInst.Close()
mycallerPreview.previewInst = Nothing
End If


In the following code I attempt to de-serialize the class by referencing the database row/column.

If cmbSavedLayouts.SelectedIndex <> -1 Then

Dim rep_row As DataRow = mycallerSelect2.select_secInst.SerializedDataDataSet.SavedReportLayouts.NewRow
rep_row = mycallerSelect2.select_secInst.SerializedDataDataSet.SavedReportLayouts.Rows(cmbSavedLayouts.SelectedIndex)
Dim str As String = rep_row("Serialized Data").ToString
Dim temp As Byte() = str.Select(AddressOf Byte.Parse).ToArray
Dim file_stream As New MemoryStream

file_stream.Write(temp, 0, temp.Count)
file_stream.Position = 0
Dim cereal_views As ListViewCereal = CType(bin_form.Deserialize(file_stream), ListViewCereal)
End If


I receive the unhandled exception "Input Stream is not a valid binary format" when I try to deserialize file_stream. I'm fairly new to this so any help is appreciated!

Answer

You have several errors. First, there is this:

Dim byteArray() As Byte = file_stream.GetBuffer()

The buffer is always larger than the stored data; sometimes much larger (by 70-80% !), so that should use ToArray() to get just the data. Next is this:

For Each bit As Byte In byteArray
    builder.Append(bit.ToString)
Next

I have no idea what builder is, but it looks like a StringBuilder. It would be simplest to save the byteArray to a VarBinary column. For string storage though, you should use a Base64 string which can easily be converted back to a byte array:

Dim serData As String = Convert.ToBase64String(memStrm.ToArray())

So, serializing and storing should be something like:

Dim B64Data As String
Using ms As New MemoryStream
    Dim bf As New BinaryFormatter
    bf.Serialize(ms, cereal)
    B64Data = Convert.ToBase64String(ms.ToArray())
End Using

' no idea what this is, just copied it
report_row("Serialized Data") = B64Data 

Deserializing would be the reverse:

' get data, unbox
Dim B64Data = dr.Field(Of String)("Serialized Data")

' I have no idea if these types are correct, just copying them
Dim cereal_views As ListViewCereal
Using ms As New MemoryStream(Convert.FromBase64String(B64Data ))
    Dim bf As New BinaryFormatter
    cereal_views = CType(bf.Deserialize(ms), ListViewCereal)
End Using