Serializing a Hashtable

M

MioTheGreat

I know how to take a single hashtable, and then use a binaryformatter
and a filestream to dump it to a file, but I need to serialize and
deserialize a hashtable inside a class. I've been trying this:

[XmlIgnore]
public Hashtable Directions;

public byte[] DirectionsSerialized
{
get
{
byte[] bData = new byte[1024];
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream(bData);
memoryStream.Position = 0;
formatter.Serialize(memoryStream, Directions);

return bData;
}
set
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.Write(value, 0, value.Length);
BinaryFormatter bf = new BinaryFormatter();
memoryStream.Position = 0;
Directions = (Hashtable)bf.Deserialize(memoryStream);
}
}



Which appears to serialize fine, but upon deserialization, it throws an
error:

"'', hexadecimal value 0x1B, is an invalid character. Line 299,
position 18."

Thanks guys.
 
N

Nicholas Paldino [.NET/C# MVP]

Mio,

A few things.

The first is that you don't really have to initialize the memory stream
with your array when serializing the instance, since it will allocate space
as needed when the serializer writes to it.

The other thing about this is that when you pass the byte array to the
constructor, it makes the memory stream fixed-size. So if you need more
than one kilobyte for the serialized instance, it will throw an exception.

Additionally, when you are returning the byte array, it contains extra
bytes that are not part of the serialized instance (in the case where you
need less than 1K).

Your get code should look like this:

// Create the formatter.
BinaryFormatter formatter = new BinaryFormatter();

// Create the stream.
using (MemoryStream memoryStream = new MemoryStream())
{
// No need to set the position, since it is already at 0.
// Serialize the instance.
formatter.Serialize(memoryStream, Directions);

// Return the array. This will be properly sized.
return memoryStream.ToArray();
}

Now, when dealing with deserializing the instance, your code should work
just fine. However, it could stand to be cleaned up, like so:

// Pass the value into the memory stream, since we are just reading.
using (MemoryStream memoryStream = new MemoryStream(value))
{
// Create the formatter.
BinaryFormatter bf = new BinaryFormatter();

// Set the hashtable.
Directions = (Hashtable) bf.Deserialize(memoryStream);
}

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


I know how to take a single hashtable, and then use a binaryformatter
and a filestream to dump it to a file, but I need to serialize and
deserialize a hashtable inside a class. I've been trying this:

[XmlIgnore]
public Hashtable Directions;

public byte[] DirectionsSerialized
{
get
{
byte[] bData = new byte[1024];
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream memoryStream = new MemoryStream(bData);
memoryStream.Position = 0;
formatter.Serialize(memoryStream, Directions);

return bData;
}
set
{
MemoryStream memoryStream = new MemoryStream();
memoryStream.Write(value, 0, value.Length);
BinaryFormatter bf = new BinaryFormatter();
memoryStream.Position = 0;
Directions = (Hashtable)bf.Deserialize(memoryStream);
}
}



Which appears to serialize fine, but upon deserialization, it throws an
error:

"'', hexadecimal value 0x1B, is an invalid character. Line 299,
position 18."

Thanks guys.
 
H

Helge Jensen

I know how to take a single hashtable, and then use a binaryformatter
and a filestream to dump it to a file, but I need to serialize and
deserialize a hashtable inside a class.

You could simply mark the containing class serializable, and let the
caller store that, but lookin at you example code I suspect you wish to
run some transformation when serializing/deserializing.

If that is the case, you can use a variant of the Memento pattern, where
you generate an opaque "memento" object that can be used to restore the
state. This object can be serialized by the caller if need be.

// not serializable
public class Foo {
// loads of state in here, perhaps duplicated
// references for efficiency and whatnot

[Serializable]
protected class Memento {
public Hashtable Directions;
public Memento(Foo foo) {
this.Directions = extract_direction_state(foo);
}
}
public object DirectionMemento {
get {
return new Memento(()); }
set {
reestablish_direction_state((Memento)value); }
}
}
}

The user will then do:

Foo foo = new Foo();
// lots of stuff, then need to save foo state:
someFormatter.Serialize(someStream, foo.DirectionMemento);
// do stuff, later restore foo state:
foo.DirectionMemento = someFormatter.Deserialize(someStream);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top