0

在我的应用程序中,我有一个从一些 XML 文件创建的相当大的对象。xml 文件大小约为 30MB,我从这个 xml 文件中的二进制序列化对象将是 8~9MB。有趣的是,如果我用例如 WinRar 压缩这个二进制文件,它将只有 1~2MB。

有没有办法增加对象本身的压缩级别?或者我应该通过手动编写代码来使用另一种压缩级别,以便在保存或解压缩之后再加载回程序之前压缩文件?

以防万一,这是我用来将对象另存为文件的代码:

    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;
    }

更新 我试图通过添加 a 来更改我的代码,GZIPSTREAM但它似乎没有做任何事情!或者也许我的实现是错误的?

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;
}
4

1 回答 1

5

FileStreamDeflateStreamwith包裹你CompressionMode.Compress- 将它传递给序列化程序。然后反序列化,将 a 包裹FileStreamDeflateStreamwith 中CompressionMode.Decompress

请注意Close,您应该使用using语句而不是显式调用,例如

using (FileStream fileStream = ...)
using (DeflateStream deflateStream = new DeflateStream(fileStream, 
                                                      CompressionMode.Compress))
{
    formatter.Serialize(deflateStream, proj);
}

您可以GZipStream以相同的方式使用 - 尝试两者,看看哪个可以为您提供更好的压缩(或更好的性能,如果您关心的话)。

请注意这种方法如何将序列化方面与压缩方面分开,将两者组合在一起,同时保持良好的关注点分离。序列化代码只是写入流而不关心数据会发生什么,而压缩代码只是压缩给出的内容而不关心数据的含义。

于 2012-08-24T09:19:55.383 回答