当前位置: 首页 > article >正文

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

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

二、增加序列化器类

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

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.kler.cn/a/510047.html

相关文章:

  • 计算机网络 (50)两类密码体制
  • Vue前端框架概述
  • Java 视频处理:基于 MD5 校验秒传及 ffmpeg 切片合并的实现
  • python中的RPA->playwright自动化录制脚本实战案例笔记
  • QT:IconButton的动画效果
  • 深度学习在文本情感分析中的应用
  • python之使用列表推导式实现快速排序算法
  • VUE的设置密码强校验的功能
  • 用户中心项目教程(三)---再谈nvm,nodejs和神器Geek
  • 【LFS/从0构建Linux系统】软件包与补丁安装及环境配置
  • MySQL备份案例: mysqldump+binlog实现完全+增量备份
  • 【Kotlin】上手学习之类型篇
  • 【Linux网络编程】序列化与反序列化
  • Jvm垃圾回收机制与常见算法
  • MindAgent:基于大型语言模型的多智能体协作基础设施
  • vue项目引入阿里云svg资源图标
  • SpringMVC (2)
  • 基于C#实现多线程启动停止暂停继续
  • 计算机网络介质访问控制全攻略:从信道划分到协议详解!!!
  • Redis瓶颈和调优
  • FileSaver.js:轻松实现浏览器文件下载
  • Windows 蓝牙驱动开发-BLE低功耗
  • 【React】脚手架进阶
  • python_在钉钉群@人员发送消息
  • 亚博microROS 机器人配置与控制
  • STM32 FreeRTOS内存管理简介