求CArchive序列化MFC C++中CTime的格式说明及字节解析
解析CArchive序列化的CTime并转换为QDateTime
1. CTime的CArchive序列化格式拆解
MFC官方文档TN002并未明确说明CTime的具体序列化格式,但我们可以通过MFC源码推导得出。针对你提供的8字节数据:0x0a 0x00 0x00 0x80 0x1b 0x0a 0x96 0x5d
逐段解析含义:
- 第0-1字节(0x0a 0x00):小端存储的
WORD类型版本号,CTime序列化的固定版本为10(0x0a)。 - 第2-3字节(0x00 0x80):小端存储的
WORD类型标记位,其中0x8000位表示当前CTime对象有效(非空/未初始化状态)。如果该位未置1,则代表这是一个无效的CTime。 - 第4-7字节(0x1b 0x0a 0x96 0x5d):小端存储的
__time32_t(32位整数)时间戳,代表从1970年1月1日UTC到目标时间的秒数。将字节逆序转换为十六进制值0x5d960a1b,对应十进制1569964571,即UTC时间2019-10-01 12:36:11。
注:较新的MFC版本中,针对2038年之后的时间,可能会使用64位的
__time64_t进行序列化,对应总长度为12字节(2字节版本号+2字节标记位+8字节时间戳),你的样本数据属于32位时间戳的版本。
2. 使用QDataStream转换为QDateTime
以下是读取序列化字节并转换为QDateTime的具体步骤:
步骤1:读取原始字节
必须将QDataStream设置为小端字节序,以匹配MFC的存储方式:
QByteArray rawData = ...; // 你的8字节CArchive序列化数据 QDataStream in(&rawData, QIODevice::ReadOnly); in.setByteOrder(QDataStream::LittleEndian); WORD version; WORD validityFlag; quint32 epochSeconds; in >> version >> validityFlag >> epochSeconds;
步骤2:校验与转换
- 校验版本号:确保
version == 10,确认是合法的CTime序列化数据。 - 校验有效性:通过
validityFlag & 0x8000判断CTime是否有效。 - 转换为QDateTime:时间戳基于UTC,可根据需求转换为本地时区:
QDateTime result; if (validityFlag & 0x8000) { result = QDateTime::fromSecsSinceEpoch(epochSeconds, Qt::UTC); // 如需转换为本地时区,取消下方注释: // result = result.toLocalTime(); } else { result = QDateTime(); // 代表无效/未初始化的CTime }
3. 关键注意事项
- CArchive始终使用小端字节序存储数据,因此必须设置QDataStream为
LittleEndian,否则解析会出错。 - 32位
__time32_t时间戳的有效范围是1970-01-01至2038-01-19,若遇到12字节的序列化数据,则是使用64位__time64_t存储的跨2038年时间。 - 由于官方文档未提及该细节,上述格式是通过分析MFC的
CTime::Serialize()实现代码得出的。
内容的提问来源于stack exchange,提问作者0nePunchMan
相关产品推荐
相关产品推荐

