QT开发技术 【基于TinyXml2的对类进行序列化和反序列化】 二

embedded/2025/1/21 1:20:25/

一、对上一篇进行优化和进一步完善

二、增加序列化器类

需要序列化的类继承该类进行操作

class CXmlSerializer
{
public:CXmlSerializer() = default;virtual ~CXmlSerializer() = default;bool Serialize(std::string& strXml);bool Deserialize(const std::string& xml);virtual bool ToXml(XMLElement* parentElem, bool bIsSerialize = true);virtual bool SaveToFile(const std::string& strFilePath);virtual bool LoadFromFile(const std::string& strFilePath);
};#include "../Include/XmlImplement.h"
#include "../Include/XmlFile.h"bool CXmlSerializer::Serialize(std::string& strXml)
{XMLDocument doc;XMLDeclaration* declaration = doc.NewDeclaration();declaration->SetValue("xml version=\"1.0\" encoding=\"GB2312\"");doc.InsertFirstChild(declaration);XMLElement* rootElem = doc.NewElement("Root");if (!ToXml(rootElem, true)){return false;}doc.InsertEndChild(rootElem);XMLPrinter printer;doc.Accept(&printer);strXml = printer.CStr();return true;
}bool CXmlSerializer::Deserialize(const std::string& xml)
{XMLDocument doc;XMLError result = doc.Parse(xml.c_str());if (result != XML_SUCCESS) {std::cerr << "Failed to parse XML: " << XMLDocument::ErrorIDToName(result) << std::endl;return false;}XMLElement* rootElem = doc.RootElement();if (!rootElem) {return false;}if (!ToXml(rootElem, false)){return false;}return true;
}bool CXmlSerializer::ToXml(XMLElement* parentElem, bool bIsSerialize)
{return false;
}bool CXmlSerializer::SaveToFile(const std::string& strFilePath)
{CXmlFile file(strFilePath);return file.Write(this);
}bool CXmlSerializer::LoadFromFile(const std::string& strFilePath)
{CXmlFile file(strFilePath);return file.Read(this);
}

三、增加XmlFile类进行文件读取和保存

#pragma once#include "XmlImplement.h"
#include "XmlSerializerExportLib.h"class XML_SERIALIZER_EXPORT CXmlFile
{
public:explicit CXmlFile(const std::string& strFileName);virtual ~CXmlFile() = default;bool Read(CXmlSerializer* pXmlSerializer);bool Write(CXmlSerializer* pXmlSerializer);private:std::string m_strFileName;
};
#include "../Include/XmlFile.h"
#include <fstream>CXmlFile::CXmlFile(const std::string& strFileName)
{m_strFileName = strFileName;
}bool CXmlFile::Read(CXmlSerializer* pXmlSerializer)
{if (!pXmlSerializer){return false;}std::ifstream ifs(m_strFileName.c_str());if (!ifs.is_open()){return false;}std::string strXml((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());ifs.close();if (strXml.empty()){return false;}return pXmlSerializer->Deserialize(strXml);
}bool CXmlFile::Write(CXmlSerializer* pXmlSerializer)
{if (!pXmlSerializer){return false;}std::string strXml;if (!pXmlSerializer->Serialize(strXml)){return false;}std::ofstream ofs(m_strFileName.c_str());if (!ofs.is_open()){return false;}ofs << strXml;ofs.close();return true;
}

在序列化器基类中调用,简化代码

四、调整CXmlImplement 实现类 使用 unique_ptr 管理内存,

静态库被调用时 普通指针析构会崩溃 替换为 unique_ptr 管理内存

class  CXmlImplement {
public:template <typename T>static void WriteElement(XMLElement* parentElem, const std::string& elementName, const T& value) {XMLElement* elem = parentElem->GetDocument()->NewElement(elementName.c_str());elem->SetText(value);parentElem->InsertEndChild(elem);}static void WriteElement(XMLElement* parentElem, const std::string& elementName, const std::string& value) {XMLElement* elem = parentElem->GetDocument()->NewElement(elementName.c_str());elem->SetText(value.c_str());parentElem->InsertEndChild(elem);}template <typename T>static void WriteSTLElement(XMLElement* parentElem, const std::string& elementName, const std::vector<T>& values) {XMLElement* vectorElem = parentElem->GetDocument()->NewElement(elementName.c_str());if (!vectorElem){return;}for (const auto& value : values) {WriteElement(vectorElem, elementName + "Item", value);}parentElem->InsertEndChild(vectorElem);}template <typename T>static void ReadElement(XMLElement* parentElem, const std::string& elementName, T& value) {XMLElement* elem = parentElem->FirstChildElement(elementName.c_str());if (elem) {value = std::stoi(elem->GetText());}}static void ReadElement(XMLElement* parentElem, const std::string& elementName, std::string& value) {XMLElement* elem = parentElem->FirstChildElement(elementName.c_str());if (elem) {value = elem->GetText();}}template <typename T>static void ReadSTLElement(XMLElement* parentElem, const std::string& elementName, std::vector<T>& values) {XMLElement* vectorElem = parentElem->FirstChildElement(elementName.c_str());if (!vectorElem){return;}for (XMLElement* elem = vectorElem->FirstChildElement(); elem; elem = elem->NextSiblingElement()){T value;ReadElement(elem, elem->Name(), value);values.push_back(value);}}static void WriteElementObject(XMLElement* parentElem, const std::string& elementName,CXmlSerializer* pXmlSerializer) {XMLElement* elem = parentElem->GetDocument()->NewElement(elementName.c_str());pXmlSerializer->ToXml(elem);parentElem->InsertEndChild(elem);}template <typename T>static void WriteElementObject(XMLElement* parentElem, const std::string& elementName, const std::vector<std::unique_ptr<T>>& objects){XMLElement* vectorElem = parentElem->GetDocument()->NewElement(elementName.c_str());for (const auto& object : objects) {WriteElementObject(vectorElem, elementName + "Item", object.get());}parentElem->InsertEndChild(vectorElem);}static void ReadElementObject(XMLElement* parentElem, const std::string& elementName, CXmlSerializer* pXmlSerializer, bool array = false){XMLElement* elem;if (array){elem = parentElem;}else{elem = parentElem->FirstChildElement(elementName.c_str());}if (elem) {pXmlSerializer->ToXml(elem, false);}}template <typename T>static void ReadElementObject(XMLElement* parentElem, const std::string& elementName, std::vector<std::unique_ptr<T>>& vecObjs){XMLElement* objectElem = parentElem->FirstChildElement(elementName.c_str());for (XMLElement* elem = objectElem->FirstChildElement(); elem; elem = elem->NextSiblingElement()){std::unique_ptr<T> pXmlSerializer = std::make_unique<T>();ReadElementObject(elem, elem->Name(), pXmlSerializer.get(), true);vecObjs.push_back(std::move(pXmlSerializer));}}};

五、测试

测试代码如下

#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "../../XmlSerialize/Include/XmlSerializer.h"class CStudent : public CXmlSerializer
{
public:CStudent(){m_nStudentID = 1;std::cout << "Constructor CStudent" << std::endl;}~CStudent(){std::cout << "Destructor CStudent" << std::endl;}XML_SERIALIZER_BEGIN(CStudent)XML_SERIALIZER_VAR("学号", m_nStudentID)XML_SERIALIZER_VAR("姓名", m_strName)XML_SERIALIZER_VAR("年龄", m_nAge)XML_SERIALIZER_VAR("性别", m_nSex)XML_SERIALIZER_END()int m_nStudentID;std::string m_strName;int m_nAge;int m_nSex;
};  class CClass : public CXmlSerializer
{
public:CClass(){std::cout << "Constructor CClass" << std::endl;}~CClass(){m_vecStudents.clear();std::cout << "Destructor CClass" << std::endl;}XML_SERIALIZER_BEGIN(CClass)XML_SERIALIZER_VAR("班级名称", m_strName)XML_SERIALIZER_VAR("班级ID", m_nClassID)XML_SERIALIZER_ARRAY("学生列表", m_vecStudents)XML_SERIALIZER_END()std::string m_strName;int m_nClassID;std::vector<std::unique_ptr<CStudent>> m_vecStudents;
};void TestXml()
{std::unique_ptr<CStudent> pStudent = std::make_unique<CStudent>();pStudent->m_nStudentID = 1001;pStudent->m_strName = "张三";pStudent->m_nAge = 20;pStudent->m_nSex = 1;pStudent->SaveToFile("E:/Project/Inlib/Base/Examples/Bin/Debug/student.xml");std::unique_ptr<CStudent> pStudent2 = std::make_unique<CStudent>();pStudent2->LoadFromFile("E:/Project/Inlib/Base/Examples/Bin/Debug/student.xml");std::cout << pStudent2->m_nStudentID << std::endl;std::cout << pStudent2->m_strName << std::endl;pStudent2->m_strName = "李四";pStudent2->m_nStudentID = 1002;CClass class1;class1.m_strName = "1班";class1.m_nClassID = 101;class1.m_vecStudents.push_back(std::move(pStudent));class1.m_vecStudents.push_back(std::move(pStudent2));class1.SaveToFile("E:/Project/Inlib/Base/Examples/Bin/Debug/class.xml");std::cout << "------class Begin--------------" << std::endl;CClass class2;class2.LoadFromFile("E:/Project/Inlib/Base/Examples/Bin/Debug/class.xml");std::cout << class2.m_strName << std::endl;
}int main()
{TestXml();return 0;
}

运行在这里插入图片描述
文件正常
在这里插入图片描述
如果文章帮到你,动动小手点赞 (-_-)

上一篇文章链接 QT开发技术 【基于TinyXml2的对类进行序列化和反序列化】一


http://www.ppmy.cn/embedded/155634.html

相关文章

JAVA:责任链模式(Chain of Responsibility Pattern)的技术指南

1、简述 责任链模式是一种行为型设计模式,用于通过将请求沿着一条链传递来处理请求,直到链上的某个处理者能够处理它为止。该模式能够动态地组织多个处理对象,避免请求发送者和接收者之间的直接耦合。 本文将详细介绍责任链模式的概念、结构、优缺点以及实际应用案例。 设…

springboot音乐播放器系统

Spring Boot音乐播放器系统是一个基于Spring Boot框架开发的音乐播放平台&#xff0c;旨在为用户提供高效、便捷的音乐播放体验。 一、系统背景与意义 随着互联网的飞速发展和人们对音乐娱乐需求的不断增长&#xff0c;音乐播放器已经成为人们日常生活中不可或缺的一部分。传…

意图颠覆电影行业的视频生成模型:Runway的Gen系列

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍Runway开发的视频生成模型Gen系列&#xff0c;包括Gen-1、Gen-2和Gen3 Alpha等&#xff0c;这些模型每次发布都震惊AI圈&#xff0c;荣获多个视频生成的…

Vue进阶之旅:核心技术与页面应用实战(路由进阶)

文章目录 一、路由模块封装二、声明式导航&#xff08;一&#xff09;导航链接与高亮&#xff08;二&#xff09;声明式导航传参1. 查询参数传参2. 动态路由传参 三、路由重定向、404 与模式设置&#xff08;一&#xff09;路由重定向&#xff08;二&#xff09;路由 404&#…

【2024年华为OD机试】(C卷,100分)- 求满足条件的最长子串的长度 (Java JS PythonC/C++)

一、问题描述 题目解析 我们需要找到一个字符串中最长的子串,该子串满足以下条件: 子串中只能包含一个字母(a~z 或 A~Z),其余字符必须是数字。字母可以在子串中的任意位置。如果字符串中没有满足条件的子串(例如全是字母或全是数字),则返回 -1。 解题思路 我们可以…

【Golang 面试题】每日 3 题(三十六)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

腾讯云AI代码助手评测:如何智能高效完成Go语言Web项目开发

腾讯云AI代码助手评测&#xff1a;如何智能高效完成Go语言Web项目开发 ?? 文章目录 腾讯云AI代码助手评测&#xff1a;如何智能高效完成Go语言Web项目开发 ?? 背景引言开发环境介绍腾讯云AI代码助手使用实例 1. 代码补全2. 技术对话3. 代码优化4. 规范代码5. Bug处理 获得…

命令模式详解与应用

在软件开发的过程中&#xff0c;我们经常会遇到需要对操作进行抽象和封装的场景。比如&#xff0c;在一个图形绘制软件中&#xff0c;用户可能执行绘制图形、撤销绘制、保存图形等操作。这些操作不仅需要被执行&#xff0c;还可能需要被记录、撤销或重做。命令模式&#xff08;…