From: tutiplain on
Hi all,

This is my first post on this forum. I really hope someone on here can
help me, I've been trying to fix this for over a month now, with no success,
and posts on Microsoft forums have gone unanswered.

I am trying to serialize a generic object (which is marked as serializable,
of course) to a Base64 string, writing this string to xml, then reading back
the base64 string and deserializing. However, when I deserialize, I get this
error Message:

Binary stream '0' does not contain a valid BinaryHeader. Possible causes are
invalid stream or object version change between serialization and
deserialization.

I have crosschecked the written values before and after writing them as
base64 and they were the same. Here is my code:

Public Function Base64EncodeObject(ByVal obj As Object) As String
Dim EncodedObject As String
Dim unienc As New System.Text.UnicodeEncoding()

EncodedObject = ""

'Serialize into byte buffer
Dim ser As New System.Runtime.Serialization.Formatters.Binary.
BinaryFormatter()
Dim ms As New System.IO.MemoryStream()
ser.Serialize(ms, obj)
ms.Seek(0, IO.SeekOrigin.Begin)

Dim buffer(ms.Length) As Byte
ms.Read(buffer, 0, ms.Length - 1)
bar = buffer
EncodedObject = System.Convert.ToBase64String(buffer,
Base64FormattingOptions.None)
ms.Close()

Return EncodedObject
End Function

Public Function Base64DecodeObject(ByVal EncodedObject As String) As
Object
Dim UnserializedObject As Object
Dim ser As New System.Runtime.Serialization.Formatters.Binary.
BinaryFormatter

Dim buffer As Byte()
buffer = System.Convert.FromBase64String(EncodedObject)
Dim ms As New System.IO.MemoryStream(buffer, True)
Dim buffer2(buffer.Length - 1) As Byte

Dim index As Integer
index = 0
While index <= buffer.Length - 1
buffer2(index) = ms.ReadByte
index = index + 1
End While

Dim ms2 As New System.IO.MemoryStream(buffer2, False)
ms2.Position = 0
UnserializedObject = ser.Deserialize(ms2)
ms.Close()
Return UnserializedObject
End Function


Any information will be greatly appreciated.

From: Armin Zingler on
First, you should switch Option Strict On.

See inline...


> Public Function Base64EncodeObject(ByVal obj As Object) As String

....

> Dim buffer(ms.Length) As Byte


Dim buffer(CInt(ms.Length) - 1) As Byte 'minus one


> ms.Read(buffer, 0, ms.Length - 1)

ms.Read(buffer, 0, ms.Length)


> Public Function Base64DecodeObject(ByVal EncodedObject As String) As
> Object
> Dim UnserializedObject As Object
> Dim ser As New System.Runtime.Serialization.Formatters.Binary.
> BinaryFormatter
>
> Dim buffer As Byte()
> buffer = System.Convert.FromBase64String(EncodedObject)
> Dim ms As New System.IO.MemoryStream(buffer, True)
> Dim buffer2(buffer.Length - 1) As Byte
>
> Dim index As Integer
> index = 0
> While index <= buffer.Length - 1
> buffer2(index) = ms.ReadByte
> index = index + 1
> End While
>
> Dim ms2 As New System.IO.MemoryStream(buffer2, False)
> ms2.Position = 0
> UnserializedObject = ser.Deserialize(ms2)
> ms.Close()
> Return UnserializedObject
> End Function

Data flow:

string -> buffer -> memorystream -> buffer2 -> memorystream -> object

Do I see this right? Why not

string -> buffer -> memorystream -> object

?

This works, too:

Public Shared Function Base64DecodeObject( _
ByVal EncodedObject As String) As Object
Dim ser As New
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

Dim buffer As Byte()
buffer = System.Convert.FromBase64String(EncodedObject)
Using ms As New System.IO.MemoryStream(buffer)
Return ser.Deserialize(ms)
End Using

End Function



Armin
From: tutiplain on
Hi, thanks for your reply

> Dim buffer(CInt(ms.Length) - 1) As Byte 'minus one

I cannot do this, as the MemoryStream object is not initialized until later,
based on the size of the buffer.


>string -> buffer -> memorystream -> buffer2 -> memorystream -> object

Yes, I did it this way to ensure that the data really was inside the buffer.
Obviously, it was. Obviously, it also generated the same error.

>This works, too:
>
> Public Shared Function Base64DecodeObject( _
> ByVal EncodedObject As String) As Object
> Dim ser As New
>System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
>
> Dim buffer As Byte()
> buffer = System.Convert.FromBase64String(EncodedObject)
> Using ms As New System.IO.MemoryStream(buffer)
> Return ser.Deserialize(ms)
> End Using
>
> End Function
>

I tried this too, but got the same error message. I have read that this
might have to do with incompatible versions of the .net framework, but it
can't be as I am running the application on the same computer. Please, any
additional suggestions are welcome.

From: Armin Zingler on
tutiplain schrieb:
> Hi, thanks for your reply
>
>> Dim buffer(CInt(ms.Length) - 1) As Byte 'minus one
>
> I cannot do this, as the MemoryStream object is not initialized until later,
> based on the size of the buffer.

I'm afraid, I don't understand what you mean. If you want to copy the
whole memory stream with no additional byte into the byte array, the
upper bound of the array must be the length of the stream minus one.

I tried it with your code and got the same exception. With mine it works.


The problem is that

EncodedObject = System.Convert.ToBase64String(buffer,
Base64FormattingOptions.None)

converts the whole buffer. If there is one byte too much, the output
string is wrong.




Armin
From: tutiplain on
Hi again,

I changed my code to the following, following your suggestion about using
only one byte array:

Public Function Base64DecodeObject3(ByVal EncodedObject As String) As Object
Dim UnserializedObject As Object
Dim ser As New System.Runtime.Serialization.Formatters.Binary.
BinaryFormatter

Dim buffer As Byte()
buffer = System.Convert.FromBase64String(EncodedObject)

Dim ms As New System.IO.MemoryStream(buffer, True)
ms.Position = 0

ms.Flush()

UnserializedObject = ser.Deserialize(ms)

ms.Close()
Return UnserializedObject
End Function

As you can see, I declare the byte array before the MemoryStream object. I
then declare ms using the buffer. This creates a stream that is the same
size of the array, with the bytes in it. Therefore, I cannot do what you
suggested about declaring the array as Dim buffer(CInt(ms.Length) - 1) As
Byte, although their might be a way around this.

I also tried out your code:
Public Shared Function Base64DecodeObject(ByVal EncodedObject As String) As
Object
Dim ser As New System.Runtime.Serialization.Formatters.Binary.
BinaryFormatter()

Dim buffer As Byte()
buffer = System.Convert.FromBase64String(EncodedObject)
Using ms As New System.IO.MemoryStream(buffer)
Return ser.Deserialize(ms)
End Using

End Function

It still threw the Exception. Am I missing something? Could we be using
different .net versions (my project is currently set to compile for .net 3.5)?
I am using VB 2008 Express. Could I be missing a service pack?

I also tried my original code on two different computers, so it's probably
not an .net installation issue either.

Thanks again for your help and quick replies.

Armin Zingler wrote:
>tutiplain schrieb:
>> Hi, thanks for your reply
>>
>>> Dim buffer(CInt(ms.Length) - 1) As Byte 'minus one
>>
>> I cannot do this, as the MemoryStream object is not initialized until later,
>> based on the size of the buffer.
>
>I'm afraid, I don't understand what you mean. If you want to copy the
>whole memory stream with no additional byte into the byte array, the
>upper bound of the array must be the length of the stream minus one.
>
>I tried it with your code and got the same exception. With mine it works.
>
>The problem is that
>
> EncodedObject = System.Convert.ToBase64String(buffer,
>Base64FormattingOptions.None)
>
>converts the whole buffer. If there is one byte too much, the output
>string is wrong.
>
>Armin