MFC - CArchive/内存之间的序列化应用细节

文章目录

    • [MFC - CArchive/内存之间的序列化应用细节](#MFC - CArchive/内存之间的序列化应用细节)
    • 概述
    • 笔记
    • END

MFC - CArchive/内存之间的序列化应用细节

概述

有个参数文件, 开始直接序列化到文件.

现在优化程序, 不想这个参数文件被用户看到.

想先由参数发布程序(自己用)设置好参数后, 加个密落地.

等用户拿到后, 由程序导入到程序运行时指定的数据目录.

程序运行时, 先解密参数文件到内存, 然后再由MFC序列化到类中的变量.

查了一下, 有大神出了文章(https://www.codeproject.com/Articles/1176939/All-About-MFC-Serialization), 将MFC序列化的各种细节都讲了.

不过有些细节要自己实验才能确定. e.g. CArchive向流中序列化写入不同的内容, 这个流空间需要开多长?

针对流的序列化, 自己做了实验, 用到的实现细节都测试了.

可以在自己工程中应用(CArchive/流之间的序列化)了.

笔记

c 复制代码
void buf_save_to_ar(uint8_t* pBuf, UINT lenBuf)
{
	bool b_rc = false;
	CMemFile memFile;
	uint64_t lenFile = 0;
	
	do {
		if ((NULL == pBuf) || (0 == lenBuf))
		{
			break;
		}

		// memFile.Close(); // @todo for test, 没有attch的时候, 也不会报错.
		// lenFile = memFile.GetLength(); // 0 , 没有attach的时候, 或者关闭后, 不报错, 返回的文件长度为0

		memFile.Attach(pBuf, lenBuf);
		// lenFile = memFile.GetLength(); // 0x100, Attach Buffer后, 文件长度就是Buffer的长度

		CArchive ar(&memFile, CArchive::store);
		//ar << CString(_T("1")); // 如果buffer长度不足, 也不报错, 看来要将buffer长度给够
		 ff fe ff 01 31 00
		//ar.Flush(); // for test

		//ar << CString(_T("12")); // 如果buffer长度不足, 也不报错, 看来要将buffer长度给够
		 ff fe ff 02 31 00 32 00
		//ar.Flush(); // for test

		//ar << CString(_T("1"));
		//ar.Flush(); // ff fe ff 01 31 00

		//ar << CString(_T("2"));
		 ff fe ff 01 31 00 ff fe ff 01 32 00
		//ar.Flush(); // for test

		ar << CString(_T("hello")); // 如果buffer长度不足, 也不报错, 看来要将buffer长度给够
		// ff fe ff 05 68 00 65 00 6c 00 6c 00 6f 00 
		ar.Flush(); // for test

		// lenFile = ar.GetFile()->GetLength(); // 这个长度和序列化无关, 就是attach的buffer长度
		ar << CString(_T("world"));
		ar.Flush(); // for test

		try {
			// 如果buffer给的长度不够, 关闭ar时会报错
			// catch不住
			// 所以buffer要留够, 给序列化内容长度估算的1.1倍数, 可能靠谱一些
			ar.Close(); 

			//  ff fe ff 05 68 00 65 00 6c 00 6c 00 6f 00 ff fe ff 05 77 00 6f 00 72 00 6c 00 64 00 ed ed fd fd fd fd 
			// 可以看到留出的保险字符位置并没有被覆盖
		}
		catch (CArchiveException* e)
		{
			e->IsSerializable();
			b_rc = false;
			break;
		}

		b_rc = true;
	} while (false);
	_ASSERT(b_rc);

	memFile.Close();
}

void ar_load_from_ar(uint8_t* pBuf, UINT lenBuf)
{
	bool b_rc = false;
	CMemFile memFile;
	CString csHello;
	CString csWorld;

	do {
		if ((NULL == pBuf) || (0 == lenBuf))
		{
			break;
		}

		memFile.Attach(pBuf, lenBuf);
		CArchive ar(&memFile, CArchive::load);
		ar >> csHello;
		// now csHello is _T("hello")

		ar >> csWorld;
		// now csWorld is _T("world")

		ar.Close();

		b_rc = true;
	} while (false);
	_ASSERT(b_rc);

	memFile.Close();
}

void CTestArBufDlg::OnBnClickedButton1()
{
	uint8_t* pBuf = NULL;
	UINT lenBuf = 0; // 根据要写入的内容多少, 估算好长度后, 来开buffer
	
	CString csTmp;
	int iLenTmp = 0;
	int i = 0;

	int iCntCString = 0; 

	// 假设要序列化的是下面这2个CString
	// CString(_T("hello"))
	// CString(_T("world"))

	csTmp = _T("hello");
	iCntCString++;
	iLenTmp = csTmp.GetLength(); // 5
	lenBuf += iLenTmp;

	csTmp = _T("world");
	iCntCString++;
	iLenTmp = csTmp.GetLength(); // 5
	lenBuf += iLenTmp;

	// ff fe ff 01 31 00
	// 每次ar一次CString, 就需要增加4个字节(0xff, 0xfe, 0xff 可能是CString的类标记(以后遇到机会, 可以再试试别的数据类型), 01 代表CString的TCHAR字符数量)

	// lenBuf 现在是WCHAR的数量, 要转成uint8_t的数量
	lenBuf = lenBuf * sizeof(TCHAR);
	lenBuf += (iCntCString * 4); // 存一次CString, 就有4个字节的头信息
	lenBuf += sizeof(TCHAR); // 留个保险字节的位置
	// now lenBuf is 0x16

	// 开buffer
	pBuf = new uint8_t[lenBuf];
	_ASSERT(NULL != pBuf);

	// 自己的内存调试标记可以为0xED. MFC调试标记为0xCD, 0xFD, 0xDD
	memset(pBuf, 0xED, lenBuf);

	// test use CArchive load-from/save-to buffer
	// 如果向流中进行序列化写入, 则需要考虑开多大的流空间, 否则报错(catch不住)
	buf_save_to_ar(pBuf, lenBuf);

	// 如果是从流中载入序列化, 则不需要考虑buffer的长度, 因为这个buffer是已经确定的, 正确的(由前面的序列化写入保证)
	ar_load_from_ar(pBuf, lenBuf);

	// all ok
}

END

相关推荐
qq_433554546 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
努力学习编程的伍大侠11 分钟前
基础排序算法
数据结构·c++·算法
yuyanjingtao1 小时前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
闻缺陷则喜何志丹1 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
charlie1145141911 小时前
C++ STL CookBook
开发语言·c++·stl·c++20
小林熬夜学编程2 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
倔强的石头1062 小时前
【C++指南】类和对象(九):内部类
开发语言·c++
A懿轩A3 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
机器视觉知识推荐、就业指导3 小时前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香3 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法