Problem deserializing 2dim and jagged array..

  • Thread starter Thread starter wyrd
  • Start date Start date
W

wyrd

I've been trying to track down a deserialization error I've been
getting for a while now, and I think I found the cause. The error I
was getting is when trying to deserialize from a file.. and yes I'm
using StreamingContextStates.File. Here's the error;

"The object with ID 4097 was referenced in a fixup but has not been
registered."

The class in which I serialize is nothing more then a two dim array,
structs, a bool value, and some strings. The two dim array is made up
of structs.

Being confused as I was, I marked the two dim array so it wouldn't
serialize. Oddly enough, the deserialization worked after that (after
reserializing the altered class of course).

I tried serializing both a jagged array and a regular array; stuff[][]
and stuff[,]. Both give the deserialization error. Marking this two
dim array to not serialize is not an option, neither is using an
ArrayList in replace of it.

Is there any way to fix this? I'm still confused as to why a two dim
or jagged array will not serialize and deserialize correctly.

Thanks in advance.
 
also, can you try NestingLevel=1 ?

For example, modify the serialization attributes in the .cs file like so:
[System.Xml.Serialization.XmlArrayItemAttribute(
"Stuff",
typeof(MyStuff),
Form=System.Xml.Schema.XmlSchemaForm.Unqualified,
IsNullable=false,
NestingLevel=1)]
public MyStuff [ ][ ] stuff;

-Dino
 
It seems to work when de/serializing in XML format, however the problem
is with binary. *boggled* I uploaded the XML serialized file so you
could see what's being serialized, and also below is the relevant code
to the problem;

Serialized file: http://www.danpeverill.com/test.xml

** BEGIN CODE SNIPPETS **

// NOTE: XML and binary serialization code is identical,
// just replace one formatter for the other.

[NonSerialized]
private Bitmap _areaImages;

[NonSerialized]
private TextureBrush[][] _areaTextures;

private MapArea[][] _map;

private Size _areaSize;
private Size _mapSize;

private Rectangle _camera;

private string _name = "";
private string _desc = "";

[NonSerialized]
private bool _disposed = false;


public static Map Load(string path)
{
try {
FileStream file = new FileStream(path, FileMode.Open);
StreamingContext context = new
StreamingContext(StreamingContextStates.File);
SoapFormatter formatter = new SoapFormatter(null, context);

Map map = (Map) formatter.Deserialize(file);
file.Close();

return map;
}
catch (Exception e) {
Console.WriteLine(e.Message);
return null;
}
}


public static bool Save(Map map, string path)
{
try {
FileStream file = new FileStream(path, FileMode.Create);
StreamingContext context = new
StreamingContext(StreamingContextStates.File);
SoapFormatter formatter = new SoapFormatter(null, context);

formatter.Serialize(file, map);

file.Close();
return true;
}
catch (Exception) {
return false;
}
}

** END CODE SNIPPETS*

Any ideas on how to fix this for binary?

Thanks for the help.
 
Dan,
I don't know what the problem is. Where is the broken code? How does it
break?

I tried out your code, and it works for me. .NET Fw v1.1.

see below.

At first I thought you were talking not about Soap Serialization but XML
serialization (System.Xml.Serialization), which is a bit different. (the
NestingLevel=1 thing I suggested previously applies only to Xml
Serialization. )


// TestSerialization.cs
//
// Demonstrates SOAP and Binary serialization and de-serialization of a
given type
//
// build with: csc /debug+ /t:exe /out:TestSerialization.exe
TestSerialization.cs
//
// Fri, 01 Aug 2003 15:41
//

namespace Ionic.Test.Serialization {

[System.Serializable]
public class MapArea {
public int _x, _y;
public MapArea(int x, int y) {
_x= x;
_y= y;
}
}

[System.Serializable]
public class Map {

//[NonSerialized]
//private Bitmap _areaImages;

//[NonSerialized]
//private TextureBrush[][] _areaTextures;

private MapArea[][] _map;

private System.Drawing.Size _areaSize;
private System.Drawing.Size _mapSize;

public System.Drawing.Rectangle _camera;

private string _name = "";
private string _desc = "";

[System.NonSerialized]
private bool _disposed = false;

private static System.Random r= new System.Random();

public Map() {
// init the various fields with dummy data

int d1= r.Next(4)+3;
_map= new MapArea[d1][];
int d2;
int i,j;
for (i=0; i < d1; i++) {
d2= r.Next(5)+2;
_map= new MapArea[d2];
for (j=0; j < d2; j++)
_map[j]= new MapArea(r.Next(24007), r.Next(18732));
}

_areaSize= new System.Drawing.Size(r.Next(1000), r.Next(1000));
_mapSize= new System.Drawing.Size(r.Next(1000), r.Next(1000));
_camera= new System.Drawing.Rectangle(r.Next(1000), r.Next(1000),
r.Next(1000), r.Next(1000));
_name= "Map-" + r.Next(5555).ToString();
_desc= "Description-" + r.Next(4000).ToString() + ": Map instance
created at " + System.DateTime.Now.ToString();
}


public static Map LoadSoap(string path)
{
try {
System.IO.FileStream file = new System.IO.FileStream(path,
System.IO.FileMode.Open);
System.Runtime.Serialization.StreamingContext context =
new
System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.S
treamingContextStates.File);
System.Runtime.Serialization.Formatters.Soap.SoapFormatter formatter
=
new System.Runtime.Serialization.Formatters.Soap.SoapFormatter(null,
context);

Map map = (Map) formatter.Deserialize(file);
file.Close();

return map;
}
catch (System.Exception e) {
System.Console.WriteLine("Exception Loading: " + e.Message);
return null;
}
}


public bool SaveSoap(string path)
{
try {
System.IO.FileStream file = new System.IO.FileStream(path,
System.IO.FileMode.Create);
System.Runtime.Serialization.StreamingContext context =
new
System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.S
treamingContextStates.File);
System.Runtime.Serialization.Formatters.Soap.SoapFormatter formatter =
new System.Runtime.Serialization.Formatters.Soap.SoapFormatter(null,
context);

formatter.Serialize(file, this);
file.Close();
return true;
}
catch (System.Exception e) {
System.Console.WriteLine("Exception Saving: " + e.Message);
return false;
}
}


public bool SaveBin(string path) {
bool result=false;
try {
System.IO.FileStream stream = System.IO.File.Open(path,
System.IO.FileMode.Create);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter
=
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

bformatter.Serialize(stream, this);
stream.Close();
result=true;
}
catch (System.Exception e) {
System.Console.WriteLine("Exception Saving (binary): " + e.Message);
}
return result;
}

public static Map LoadBin(string path) {
Map map= null;
try {
System.IO.FileStream file = new System.IO.FileStream(path,
System.IO.FileMode.Open);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

map = (Map) formatter.Deserialize(file);
file.Close();
}
catch (System.Exception e) {
System.Console.WriteLine("Exception Loading: " + e.Message);
}
return map;
}


public void Dump() {
System.Console.WriteLine("MapArea (hashcode=" + this.GetHashCode() +
"):\n" +
" _map[" + _map.Length + "][]= {");
int i,j, d2;
for (i=0; i < _map.Length; i++) {
d2=_map.Length;
System.Console.Write(" MapArea[" + d2 + "] = { ");
for (j=0; j < d2; j++) {
System.Console.Write("(" + _map[j]._x + "," + _map[j]._y + "), ");
}
System.Console.WriteLine("}");
}
System.Console.WriteLine(" }\n _name= " + this._name + "\n" +
" _desc= " + this._desc + "\n" +
" _areaSize= " + this._areaSize.Height + ", " + _areaSize.Width +
"\n" +
" _mapSize= " + _mapSize.Height + ", " + _mapSize.Width + "\n" );
}



public static void Main() {
string xmlfile= "Map-" +
System.DateTime.Now.ToString("yyyy-MMM-d-hhmmss") + ".xml";
string binfile= "Map-" +
System.DateTime.Now.ToString("yyyy-MMM-d-hhmmss") + ".bin";

Map m1= new Map(); // get an instance with dummy data
m1.Dump(); // display it

Map m2= new Map(); // get a new (different) instance, new data
m2.Dump();
m2.SaveSoap(xmlfile);

Map m3= Map.LoadSoap(xmlfile); // slurp!
m3.Dump(); // should be same as dump for m2 (above)
m3.SaveBin(binfile); // burp!

Map m4= Map.LoadBin(binfile); // slurp!
m4.Dump();

}
}
}




Dan Peverill said:
It seems to work when de/serializing in XML format, however the problem
is with binary. *boggled* I uploaded the XML serialized file so you
could see what's being serialized, and also below is the relevant code
to the problem;

Serialized file: http://www.danpeverill.com/test.xml

** BEGIN CODE SNIPPETS **

// NOTE: XML and binary serialization code is identical,
// just replace one formatter for the other.

[NonSerialized]
private Bitmap _areaImages;

[NonSerialized]
private TextureBrush[][] _areaTextures;

private MapArea[][] _map;

private Size _areaSize;
private Size _mapSize;

private Rectangle _camera;

private string _name = "";
private string _desc = "";

[NonSerialized]
private bool _disposed = false;


public static Map Load(string path)
{
try {
FileStream file = new FileStream(path, FileMode.Open);
StreamingContext context = new
StreamingContext(StreamingContextStates.File);
SoapFormatter formatter = new SoapFormatter(null, context);

Map map = (Map) formatter.Deserialize(file);
file.Close();

return map;
}
catch (Exception e) {
Console.WriteLine(e.Message);
return null;
}
}


public static bool Save(Map map, string path)
{
try {
FileStream file = new FileStream(path, FileMode.Create);
StreamingContext context = new
StreamingContext(StreamingContextStates.File);
SoapFormatter formatter = new SoapFormatter(null, context);

formatter.Serialize(file, map);

file.Close();
return true;
}
catch (Exception) {
return false;
}
}

** END CODE SNIPPETS*

Any ideas on how to fix this for binary?

Thanks for the help.
 
As I said in above, the problem is when I use the BinaryFormatter. It
gives an error when trying to deserialize (refer to the original post
for error message). I only used SoapFormatter to help pinpoint where the
problem was. My mistake for copy/pasting the code that worked, it
probably added to some confusion.

If you take my sample code and change the formatter to BinaryFormatter,
it should produce an error upon deserialization. If you mark the two
dimensional array (MapArea[][]) so it won't serialize, the error goes
away. I need that two dimensional array to de/serialize properly, and I
need to do it using BinaryFormatter.

BTW I'm using framework 1.0.

Thanks for the help.
 
Back
Top