A few weeks back I wrote a class to help serialize/deserialize objects file. The file format requested was json, then compressed. After some coding/testing I settled on this design:
class StoreObjects<T>
{
public IEnumerable<T> LoadObjects()
{
List<T> loadObjectList = new List<T>();
using (Stream stream = new FileStream("fullpathtofile", FileMode.Open, FileAccess.Read, FileShare.Read))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
var js = new JavaScriptSerializer { MaxJsonLength = Int32.MaxValue };
using (GZipStream gs = new GZipStream(stream, CompressionMode.Decompress))
{
do
{
try
{
var bfs = binaryFormatter.Deserialize(gs);
T storeObject = js.Deserialize<T>(bfs as string);
loadObjectList.Add(storeObject);
}
catch (SerializationException se)
{
//see msdn.microsoft.com/b85344hz.aspx
if (se.Message.Contains("Decimal"))
throw;
//else
break;
}
} while (gs != null);
}
}
return loadObjectList;
}
public bool SaveObjects(List<T> storedObjects)
{
try
{
using (FileStream compressedFileStream = File.Create("fullpathtofile"))
{
using (GZipStream coStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
var serializer = new JavaScriptSerializer() { MaxJsonLength = Int32.MaxValue };
for (int i = 0; i < storedObjects.Count; i++)
{
var dump = serializer.Serialize(storedObjects[i]);
binaryFormatter.Serialize(compressedFileStream, dump);
}
}
}
return true;
}
catch (Exception exception)
{
//swallow exception on purpose, log error message
}
return false;
}
}
2 design decisions I'm not proud of:
- During research, we found that if we passed a very large
List
of objects, the serialize/deserialize would leak memory. So I settled on a generic class, that you have to pass in aList<T>
of the generic toSaveObjects
and get back anIEnumerable<T>
SaveObjects
. As long as your type isn't a very large list, you don't leak memory. BTW, the leak happened when I used json.net also. - In
LoadObjects
the deserialization stops via an exception check. Because of the nature of deserialize (typically done once for the object tree) and the fact I'm loading lists (see point 1), I have no other way of stopping the deserialization.
It seems to work fine, but I'm not the proud of this design.
.
as decimal separator and the other,
. \$\endgroup\$ – t3chb0t Jul 25 '16 at 8:26