如何将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
相关产品推荐
相关产品推荐

