In my application I have a rather large object created from some XML files. The xml file sizes something like 30MB, and my binary serialized object from this xml file will be like 8~9MB. Funny thing is if I compress this binary file with e.g. WinRar, it will be just 1~2MB.
Is there a way to increase compression level of the object itself? Or should I use another level of compression by manually write code for zipping the file after saving or unzip before loading back into the program?
In case, this is the code I use to save my object as file:
public static bool SaveProject(Project proj, string pathAndName)
{
bool success = true;
proj.FileVersion = CurrentFileVersion;
try
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(pathAndName, FileMode.Create, FileAccess.Write, FileShare.None);
formatter.Serialize(stream, proj);
stream.Close();
}
catch (Exception e)
{
MessageBox.Show("Can not save project!" + Environment.NewLine + "Reason: ", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
success = false;
}
return success;
}
UPDATE
I tried to change my code by adding a GZIPSTREAM but it seems that it does not do anything! Or maybe my implementation is wrong?
public static bool SaveProject(Project proj, string pathAndName)
{
bool success = true;
proj.FileVersion = CurrentFileVersion;
try
{
IFormatter formatter = new BinaryFormatter();
var stream = new FileStream(pathAndName, FileMode.Create, FileAccess.Write, FileShare.None);
var gZipStream = new GZipStream(stream, CompressionMode.Compress);
formatter.Serialize(stream, proj);
stream.Close();
gZipStream.Close();
}
catch (Exception e)
{
MessageBox.Show("Can not save project!" + Environment.NewLine + "Reason: ", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
success = false;
}
return success;
}
public static Project LoadProject(string path)
{
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
var gZipStream = new GZipStream(stream, CompressionMode.Decompress);
var obj = (Project)formatter.Deserialize(gZipStream);
stream.Close();
gZipStream.Close();
if (obj.FileVersion != CurrentFileVersion)
{
throw new InvalidFileVersionException("File version belongs to an older version of the program.");
}
return obj;
}
Wrap your
FileStreamin aDeflateStreamwithCompressionMode.Compress– pass that to the serializer. Then to deserialize, wrap aFileStreamin aDeflateStreamwithCompressionMode.Decompress.Note that instead of calling
Closeexplicitly, you should use ausingstatement, e.g.You can use
GZipStreamin the same way – try both to see which tends to give you better compression (or better performance, if you care about that).Note how this approach separates the serialization aspect from the compression aspect, composing the two while keeping good separation of concerns. The serialization code just writes to a stream without caring what happens to the data, and the compression code just compresses what it’s given without caring what the data means.