views:

566

answers:

5

Let say I have a file that contains a serialized object by BinaryFomatter. Now I want to be able to serialize another object and APPEND this on that existing file.

How can I do it?

+2  A: 

How's about this

Deserialise the contents of your first file into an object in memory, add the first object to a collection (e.g. List<YourObjectType>), add your new object to that collection, then serialise the collection (containing two objects now) on top of the existing file.

tomfanning
+3  A: 

Put your objects into a collection object and serialize like that. If you'd manage to append a binary representation of an object at the end of an existing file you'd get problems reading it back.

lewap
I'm sure that's what I just said
tomfanning
Sure that's the same. Remind however that it is possible to write an answer simultaneously and post it at almost the same time without seeing the other answers. ;)
lewap
I suppose so :-)
tomfanning
What kind of problems will you get when you read it back?
Lasse V. Karlsen
None, if the collection of objects is serialised and deserialised. You'll just get a collection back containing the same objects you started with.
tomfanning
@lassevk You'd be deserializing 1 stream to 2 object types... Which I suppose you could do by deserialize the first x bytes of the stream to object type 1 and then the next y bytes to object type 2. It's a terrible code smell if you ask me. If the objects belong together, they should be together (ie. aggregates of/internal to 1 type).
SnOrfus
+2  A: 

Actually, if you just open the stream for writing, and positioning the pointer at the end of the stream, you can serialize another object and it will be appended to the existing stream.

Deserializing will also read past the object, but not further.

Obviously, if you want random access to your objects (deserialize object nr. 17, but not everything before it), then you need an index of the positions where each object starts, but if you just want to read all objects from the start, you can just serialize them out after each other.

Lasse V. Karlsen
And how would you deserialize it afterwars? Are you sure .Net knows the serialized object size from the headers?
Elazar Leibovich
That is a very good question. I very much doubt it.
Lasse V. Karlsen
But yes, it does.
Lasse V. Karlsen
When you think about it, obviously it has to know the size, because it also just serializes sub-objects normally. It would never be able to deserialize such objects if it didn't know the size of them. So either it doesn't need to know the size, or it figures it out as it goes along.
Lasse V. Karlsen
+1  A: 

First, if what you really need is to store an array of object - put them in a container and serialize the container, as said earlier.

Now, if you really want to store two serialized object in a single file concatenated:

I'm not sure that this is possible "out of the box", but you can do two things.

  1. Use, or invent your own semi-tar file format, in which you'll write a small header in the beginning (or end) of the file that describes the content of the file (#'objects, and sizes).

  2. Write a C# code to detect the beginning and end of each serialized object yourself. I'm not entirely sure it's possible. Here is a non-official documentation of the serialization format. It contains header, however there's no guarantee that this header won't appear in the file.

Elazar Leibovich
+3  A: 

This is indeed possible. The code below appends the object.

using (var fileStream = new FileStream("C:\file.dat", FileMode.Append))
{
    var bFormatter = new BinaryFormatter();
    bFormatter.Serialize(fileStream, objectToSerialize);
}

The following code de-serializes the objects.

var list = new List<ObjectToSerialize>();    

using (var fileStream = new FileStream("C:\file.dat", FileMode.Open))
{
    var bFormatter = new BinaryFormatter();
    while (fileStream.Position != fileStream.Length)
    {
         list.Add((ObjectToSerialize)bFormatter.Deserialize(fileStream));
    }
}

Note for this to work the file must only contain the same objects.

Dominic Godin