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

C# 如何正确序列化Icon对象 避免反序列化后出现质量损失

问题根因

System.Drawing.Icon类的默认序列化实现仅会保留默认尺寸(通常为32×32)的图标帧,多尺寸、更高清的图标帧会在序列化时被直接丢弃,这就是反序列化后图标质量下降的核心原因。BinaryFormatter自身不会处理Icon的多帧数据留存,因此不能直接用来序列化Icon列表。
要实现无损序列化,核心思路是不依赖Icon类的默认序列化逻辑,直接读写Icon的完整原始字节流

无损序列化实现方案

方案1:基于BinaryFormatter的适配实现

通过提前将Icon转为完整字节流再序列化,避免默认逻辑丢弃帧数据:

序列化代码

List<Icon> icons = GetIcons(); // 获取图标列表的原有逻辑
List<byte[]> iconBytesList = new List<byte[]>();

// 逐个将Icon转为完整的原始字节数组
foreach (var icon in icons)
{
    using (MemoryStream ms = new MemoryStream())
    {
        icon.Save(ms);
        iconBytesList.Add(ms.ToArray());
    }
}

// 序列化字节数组列表,字节数据序列化无损耗
BinaryFormatter formatter = new BinaryFormatter();
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
{
    formatter.Serialize(fs, iconBytesList);
}

反序列化代码

BinaryFormatter formatter = new BinaryFormatter();
List<byte[]> iconBytesList;

// 先反序列化得到字节数组列表
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
    iconBytesList = (List<byte[]>)formatter.Deserialize(fs);
}

// 逐个将字节数组转回完整Icon对象
List<Icon> icons = new List<Icon>();
foreach (var bytes in iconBytesList)
{
    using (MemoryStream ms = new MemoryStream(bytes))
    {
        icons.Add(new Icon(ms));
    }
}

方案2:规避BinaryFormatter的更安全实现

由于BinaryFormatter存在已知的安全风险,也可以直接手动读写文件实现,无需依赖序列化器:

// 序列化写入文件
List<Icon> icons = GetIcons();
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
using (var writer = new BinaryWriter(fs))
{
    // 写入图标总数
    writer.Write(icons.Count);
    foreach (var icon in icons)
    {
        using var ms = new MemoryStream();
        icon.Save(ms);
        byte[] iconBytes = ms.ToArray();
        // 先写入当前图标字节长度,再写入字节内容
        writer.Write(iconBytes.Length);
        writer.Write(iconBytes);
    }
}

// 反序列化读取文件
List<Icon> icons = new List<Icon>();
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (var reader = new BinaryReader(fs))
{
    int iconCount = reader.ReadInt32();
    for (int i = 0; i < iconCount; i++)
    {
        int byteLen = reader.ReadInt32();
        byte[] iconBytes = reader.ReadBytes(byteLen);
        using var ms = new MemoryStream(iconBytes);
        icons.Add(new Icon(ms));
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:18:05