0

This is an offshoot of my question found at Pulling objects from binary file and putting in List<T> and the question posed by David Torrey at Serializing and Deserializing Multiple Objects.

I don't know if this is even possible or not. Say that I have an application that uses five different classes to contain the necessary information to do whatever it is that the application does. The classes do not refer to each other and have various numbers of internal variables and the like. I would want to save the collection of objects spawned from these classes into a single save file and then be able to read them back out. Since the objects are created from different classes they can't go into a list to be sent to disc. I originally thought that using something like sizeof(this) to record the size of the object to record in a table that is saved at the beginning of a file and then have a common GetObjectType() that returns an actionable value as the kind of object it is would have worked, but apparently sizeof doesn't work the way I thought it would and so now I'm back at square 1.

Community
  • 1
  • 1
Brad
  • 272
  • 2
  • 7
  • 22
  • 1
    Can you not just create a Settings object that contains everything you need and use XmlSerializer to serialize/deserialize the data? – sa_ddam213 Jan 15 '14 at 21:12
  • You know, I hadn't thought of that. For any kind of project I could foresee myself undertaking, I cannot think of a reason that your posed solution wouldn't work. If I step out even further, I could see it not working for, say, writing a file system but I'm of the mind that there are other issues at hand if you are writing a file system in C#. – Brad Jan 15 '14 at 21:24

1 Answers1

1

Several options: wrap all of your objects in a larger object and serialize that. The problem with that is that you can't deserialize just one object, you have to load all of them. If you have 10 objects that each is several megs, that isn't a good idea. You want random access to any of the objects, but you don't know the offsets in the file. The "wrapper" objcect can be something as simple as a List<object>, but I'd use my own object for better type safety.

Second option: use a fixed size file header/footer. Serialize each object to a MemoryStream, and then dump the memory streams from the individual objects into the file, remembering the number of bytes in each. Finally add a fixed size block at the start or end of the file to record the offsets in the file where the individual objects begin. In the example below the header of the file has first the number of objects in the file (as an integer), then one integer for each object giving the size of each object.

// Pseudocode to serialize two objects into the same file

// First serialize to memory    
byte[] bytes1 = object1.Serialize();
byte[] bytes2 = object2.Serialize();    

// Write header:
file.Write(2);              // Number of objects
file.Write(bytes1.Length);  // Size of first object
file.Write(bytes2.Length);  // Size of second object

// Write data:
file.Write(bytes1);
file.Write(bytes2);

The offset of objectN, is the size of the header PLUS the sum of all sizes up to N. So in this example, to read the file, you read the header like so (pseudo, again)

numObjs = file.readInt();
for(i=0..numObjs)
    size[i] = file.readInt();

After which you can compute and seek to the correct location for object N.

Third option: Use a format that does option #2 for you, for example zip. In .NET you can use System.IO.Packaging to create a structured zip (OPC format), or you can use a third party zip library if you want to roll your own zip format.

Anders Forsgren
  • 10,827
  • 4
  • 40
  • 77
  • Question on Option #2: How do you determine the size of an object in C# to know your start and stop points when reading back out? – Brad Jan 15 '14 at 21:27
  • The (serialized) size of the object is how many bytes you needed to serialize it. You will know right after you have serialized it. I'll add some pseudocode to show what I mean – Anders Forsgren Jan 15 '14 at 21:29