You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将C# XmlSerializer序列化的大文件压缩至500KB左右?

问题描述

我使用C#的XmlSerializer对包含大量成员的大型WellInfo对象进行序列化与反序列化,生成的文件体积达8~10MB,希望能将文件体积压缩至500KB左右。当前代码如下:

[Serializable]
public class WellInfo : INotifyPropertyChanged
{       
    public Int32 WellIndex { get; set; }   
    public string WellName { get; set; }
    private WellType _eWellType;     
    public WellType eWellType
    {
        get
        {
            return _eWellType;
        }
        set
        {                
             _eWellType = value;
        }
    }

    private string _strWellType;
    /// <summary>
    /// well type
    /// </summary>
    public string strWellType
    {
        get
        {
            return _strWellType;
        }
        set
        {
            _strWellType = value;
            InvokePropertyChanged("strWellType");
        }
    }
    // 大量其他对象成员
}

public static int SaveAsConfig(WellInfo info, string FullPath)
{
    if (info == null) return -1;   

    using (var fs = new FileStream(FullPath, FileMode.Create, FileAccess.Write))
    {
        using (var cryptoStream = new CryptoStream(fs, des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
        {
            XmlSerializer xs = new XmlSerializer(typeof(WellInfo));
            xs.Serialize(cryptoStream, info);
        }                   
    }
    return 0;
}

解决方案

方案1:二进制序列化 + GZip压缩

二进制序列化的体积远小于Xml,配合GZip压缩能大幅降低文件大小,同时保留你的加密逻辑:

// 序列化方法
public static int SaveAsConfig(WellInfo info, string FullPath)
{
    if (info == null) return -1;

    using (var fs = new FileStream(FullPath, FileMode.Create, FileAccess.Write))
    using (var gzipStream = new GZipStream(fs, CompressionMode.Compress))
    using (var cryptoStream = new CryptoStream(gzipStream, des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(cryptoStream, info);
    }
    return 0;
}

// 反序列化方法
public static WellInfo LoadConfig(string FullPath)
{
    using (var fs = new FileStream(FullPath, FileMode.Open, FileAccess.Read))
    using (var cryptoStream = new CryptoStream(fs, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
    using (var gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress))
    {
        var formatter = new BinaryFormatter();
        return formatter.Deserialize(gzipStream) as WellInfo;
    }
}

注意:BinaryFormatter在.NET Core/.NET 5+中已被标记为过时,若使用新版本框架,可改用System.Text.Json的二进制序列化或第三方库如MessagePack。

方案2:Json序列化(Newtonsoft.Json)+ GZip压缩

Json比Xml更简洁,配合压缩也能达到理想的体积,且可读性优于二进制:

// 需先安装Newtonsoft.Json NuGet包
public static int SaveAsConfig(WellInfo info, string FullPath)
{
    if (info == null) return -1;

    var jsonStr = JsonConvert.SerializeObject(info, Formatting.None);
    var jsonBytes = Encoding.UTF8.GetBytes(jsonStr);

    using (var fs = new FileStream(FullPath, FileMode.Create, FileAccess.Write))
    using (var gzipStream = new GZipStream(fs, CompressionMode.Compress))
    using (var cryptoStream = new CryptoStream(gzipStream, des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
    {
        cryptoStream.Write(jsonBytes, 0, jsonBytes.Length);
    }
    return 0;
}

// 反序列化方法
public static WellInfo LoadConfig(string FullPath)
{
    using (var fs = new FileStream(FullPath, FileMode.Open, FileAccess.Read))
    using (var cryptoStream = new CryptoStream(fs, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
    using (var gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress))
    using (var reader = new StreamReader(gzipStream, Encoding.UTF8))
    {
        var jsonStr = reader.ReadToEnd();
        return JsonConvert.DeserializeObject<WellInfo>(jsonStr);
    }
}

方案3:Xml序列化后直接压缩(最小改动)

如果不想替换序列化方式,可在Xml序列化后添加GZip压缩,虽然效果不如前两种,但也能显著减小体积:

public static int SaveAsConfig(WellInfo info, string FullPath)
{
    if (info == null) return -1;

    using (var fs = new FileStream(FullPath, FileMode.Create, FileAccess.Write))
    using (var gzipStream = new GZipStream(fs, CompressionMode.Compress))
    using (var cryptoStream = new CryptoStream(gzipStream, des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
    {
        XmlSerializer xs = new XmlSerializer(typeof(WellInfo));
        xs.Serialize(cryptoStream, info);
    }
    return 0;
}

// 反序列化方法
public static WellInfo LoadConfig(string FullPath)
{
    using (var fs = new FileStream(FullPath, FileMode.Open, FileAccess.Read))
    using (var cryptoStream = new CryptoStream(fs, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
    using (var gzipStream = new GZipStream(cryptoStream, CompressionMode.Decompress))
    {
        XmlSerializer xs = new XmlSerializer(typeof(WellInfo));
        return xs.Deserialize(gzipStream) as WellInfo;
    }
}

额外优化建议

  • 移除WellInfo中冗余的成员(比如示例中eWellType和strWellType可能重复存储,可只保留一个)
  • 对字符串等重复内容使用更紧凑的编码(如UTF-8替代UTF-16)
  • 若使用.NET 6+,可尝试System.Text.Json的源生成器进一步提升序列化效率和体积

内容的提问来源于stack exchange,提问作者sherry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 12:55:16