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

为CArchive结构序列化添加版本兼容:无版本号存档适配

兼容无版本号旧存档的解决方案

针对旧存档没有前置版本号的情况,核心思路是先尝试读取版本号,验证合理性后选择对应读取逻辑,不合理则回退到旧流程,具体实现如下:

关键修改点

  • 将无版本号的旧存档视为版本1,新版本写入时统一标记为版本2
  • 读取时先记录文件指针初始位置,尝试读取版本号后做有效性验证
  • 验证失败则回退指针,按旧逻辑读取,避免数据错位导致崩溃

修正后的完整序列化代码

// 序列化(写入):新版本统一写入版本号2
friend CArchive& operator<<(CArchive& rArchive, const S_MEMORIAL_INFO& rsMI)
{
    const WORD wVersion = 2;
    return rArchive << wVersion
                    << rsMI.strHost
                    << rsMI.strCohost
                    << rsMI.strZoomAttendant
                    << rsMI.strChairman
                    << rsMI.strPrayerOpen
                    << rsMI.strPrayerClose
                    << rsMI.strSpeaker
                    << rsMI.strTheme
                    << rsMI.strImagePath
                    << rsMI.strTextBeforeImage
                    << rsMI.strTextAfterImage
                    << rsMI.iImageWidthAsPercent
                    << rsMI.iSongOpen
                    << rsMI.iSongClose;
}

// 反序列化(读取):兼容无版本号的旧存档
friend CArchive& operator>>(CArchive& rArchive, S_MEMORIAL_INFO& rsMI)
{
    WORD wVersion = 0;
    CFile* pFile = rArchive.GetFile();
    const LONG originalPos = pFile->GetPosition(); // 记录初始读取位置

    // 尝试读取版本号
    try
    {
        rArchive >> wVersion;
    }
    catch (CArchiveException* e)
    {
        // 读取版本号失败,直接回退到旧逻辑
        e->Delete();
        pFile->Seek(originalPos, CFile::begin);
        goto READ_LEGACY;
    }

    // 验证版本号是否合理:只接受1或2(旧版本视为1,新版本是2)
    if (wVersion != 1 && wVersion != 2)
    {
        // 读取到的不是有效版本号,说明是旧存档,回退指针位置
        pFile->Seek(originalPos, CFile::begin);
        goto READ_LEGACY;
    }

    // 版本号有效,按版本分支读取
    rArchive >> rsMI.strHost
             >> rsMI.strCohost
             >> rsMI.strZoomAttendant
             >> rsMI.strChairman
             >> rsMI.strPrayerOpen
             >> rsMI.strPrayerClose
             >> rsMI.strSpeaker;

    rsMI.strTheme.Empty();
    if (wVersion >= 2)
    {
        rArchive >> rsMI.strTheme;
    }

    // 读取剩余字段
    return rArchive >> rsMI.strImagePath
                    >> rsMI.strTextBeforeImage
                    >> rsMI.strTextAfterImage
                    >> rsMI.iImageWidthAsPercent
                    >> rsMI.iSongOpen
                    >> rsMI.iSongClose;

READ_LEGACY:
    // 旧存档读取逻辑:无版本号,直接按原顺序读取
    return rArchive >> rsMI.strHost
                    >> rsMI.strCohost
                    >> rsMI.strZoomAttendant
                    >> rsMI.strChairman
                    >> rsMI.strPrayerOpen
                    >> rsMI.strPrayerClose
                    >> rsMI.strSpeaker
                    >> rsMI.strImagePath
                    >> rsMI.strTextBeforeImage
                    >> rsMI.strTextAfterImage
                    >> rsMI.iImageWidthAsPercent
                    >> rsMI.iSongOpen
                    >> rsMI.iSongClose;
}

补充说明

  • 版本号验证逻辑:旧存档第一个字段是CString,其序列化开头的int长度值几乎不可能是1或2(空字符串长度为0,同样会触发回退),以此区分新旧存档
  • 异常处理:捕获读取版本号时的异常(如文件读取到末尾、数据格式错误),确保程序不会崩溃
  • 代码修正:原代码中operator>>错误使用了const S_MEMORIAL_INFO&参数,反序列化需要修改对象,必须改为S_MEMORIAL_INFO&

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 23:31:06