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的对类进行序列化和反序列化】一
原文地址:https://blog.csdn.net/weixin_45397344/article/details/145202117
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!