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

Qt 5.9 XML文件写入指南

Qt 5.9 XML文件写入指南


在Qt 5.9中,有多种方法可以编写XML文件。下面我将介绍三种主要方法,并提供完整的代码示例和最佳实践。

三种XML写入方法对比

方法优点缺点适用场景
QXmlStreamWriter高效、内存占用低无树形结构大型XML文件
QDomDocument树形结构、易操作内存占用高小型XML文件、需要频繁修改
Qt XML PatternsXQuery支持复杂、学习曲线陡需要XQuery/XPath

方法1:使用QXmlStreamWriter(推荐)

这是最高效的方法,特别适合大型XML文件:

#include <QXmlStreamWriter>
#include <QFile>
#include <QDebug>
#include <QDateTime>bool writeXmlWithStreamWriter(const QString &filename)
{// 使用QSaveFile确保原子写入(防掉电丢失)QSaveFile file(filename);if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {qWarning() << "无法打开文件:" << file.errorString();return false;}QXmlStreamWriter xml(&file);xml.setAutoFormatting(true);  // 自动格式化xml.setAutoFormattingIndent(2); // 缩进2个空格// 开始文档xml.writeStartDocument();// 根元素xml.writeStartElement("Data");xml.writeAttribute("version", "1.0");xml.writeAttribute("created", QDateTime::currentDateTime().toString(Qt::ISODate));// 写入注释xml.writeComment("这是一个使用QXmlStreamWriter生成的XML文件");// 书籍信息xml.writeStartElement("Books");for (int i = 1; i <= 3; ++i) {xml.writeStartElement("Book");xml.writeAttribute("id", QString::number(i));xml.writeTextElement("Title", QString("Qt编程指南 %1").arg(i));xml.writeTextElement("Author", QString("作者 %1").arg(i));xml.writeTextElement("Year", QString::number(2015 + i));xml.writeTextElement("Price", QString::number(35.5 + i));// 添加CDATA部分xml.writeStartElement("Description");xml.writeCDATA(QString("<p>这是第%1本书的描述,包含<strong>特殊字符</strong></p>").arg(i));xml.writeEndElement(); // Descriptionxml.writeEndElement(); // Book}xml.writeEndElement(); // Books// 用户信息xml.writeStartElement("Users");xml.writeEmptyElement("User"); // 空元素xml.writeAttribute("id", "1001");xml.writeAttribute("name", "张三");xml.writeAttribute("role", "管理员");xml.writeEndElement(); // Users// 结束文档xml.writeEndElement(); // Dataxml.writeEndDocument();// 提交文件(原子操作)if (!file.commit()) {qCritical() << "文件提交失败:" << file.errorString();return false;}qDebug() << "XML文件已成功写入:" << filename;return true;
}

方法2:使用QDomDocument(DOM方式)

适合小型XML文件或需要频繁修改的场景:

#include <QDomDocument>
#include <QFile>
#include <QDebug>bool writeXmlWithDomDocument(const QString &filename)
{// 创建DOM文档QDomDocument doc("XML_DOC");// 创建处理指令QDomProcessingInstruction pi = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");doc.appendChild(pi);// 创建根元素QDomElement root = doc.createElement("Data");root.setAttribute("version", "1.0");doc.appendChild(root);// 创建注释QDomComment comment = doc.createComment("这是一个使用QDomDocument生成的XML文件");root.appendChild(comment);// 创建书籍元素QDomElement booksElement = doc.createElement("Books");root.appendChild(booksElement);for (int i = 1; i <= 3; ++i) {QDomElement bookElement = doc.createElement("Book");bookElement.setAttribute("id", i);booksElement.appendChild(bookElement);QDomElement title = doc.createElement("Title");title.appendChild(doc.createTextNode(QString("Qt高级编程 %1").arg(i)));bookElement.appendChild(title);QDomElement author = doc.createElement("Author");author.appendChild(doc.createTextNode(QString("专家 %1").arg(i)));bookElement.appendChild(author);QDomElement year = doc.createElement("Year");year.appendChild(doc.createTextNode(QString::number(2018 + i)));bookElement.appendChild(year);}// 创建用户元素QDomElement usersElement = doc.createElement("Users");root.appendChild(usersElement);QDomElement userElement = doc.createElement("User");userElement.setAttribute("id", "1002");userElement.setAttribute("name", "李四");userElement.setAttribute("role", "编辑");usersElement.appendChild(userElement);// 写入文件QSaveFile file(filename);if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {qWarning() << "无法打开文件:" << file.errorString();return false;}// 使用缩进格式输出QTextStream out(&file);out.setCodec("UTF-8");doc.save(out, 2); // 缩进2个空格if (!file.commit()) {qCritical() << "文件提交失败:" << file.errorString();return false;}qDebug() << "XML文件已成功写入:" << filename;return true;
}

方法3:使用Qt XML Patterns(XQuery)

适合需要复杂XML转换的场景:

#include <QXmlQuery>
#include <QXmlFormatter>
#include <QBuffer>
#include <QFile>
#include <QDebug>bool writeXmlWithXmlPatterns(const QString &filename)
{// 创建XML查询QXmlQuery query(QXmlQuery::XQuery10);// 定义XQuery生成XMLQString xquery = R"(declare variable $books external;<Data version="1.0"><Books>{for $book in $books/Bookreturn $book}</Books><Users><User id="1003" name="王五" role="读者"/></Users></Data>)";// 绑定变量QBuffer booksData;booksData.open(QIODevice::ReadWrite);booksData.write(R"(<Books><Book id="4"><Title>Qt多线程编程</Title><Author>赵六</Author><Year>2022</Year></Book><Book id="5"><Title>QML高级技巧</Title><Author>钱七</Author><Year>2023</Year></Book></Books>)");booksData.seek(0);query.bindVariable("books", &booksData);query.setQuery(xquery);if (!query.isValid()) {qWarning() << "无效的XQuery";return false;}// 执行查询并格式化输出QBuffer outputBuffer;outputBuffer.open(QIODevice::ReadWrite);QXmlFormatter formatter(query, &outputBuffer);formatter.setIndentationDepth(2);if (!query.evaluateTo(&formatter)) {qWarning() << "XQuery执行失败";return false;}outputBuffer.seek(0);// 写入文件QSaveFile file(filename);if (!file.open(QIODevice::WriteOnly)) {qWarning() << "无法打开文件:" << file.errorString();return false;}file.write(outputBuffer.data());if (!file.commit()) {qCritical() << "文件提交失败:" << file.errorString();return false;}qDebug() << "XML文件已成功写入:" << filename;return true;
}

使用示例

#include <QCoreApplication>int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QString filename = "example.xml";// 方法1:使用QXmlStreamWriterif (writeXmlWithStreamWriter("stream_writer.xml")) {qDebug() << "方法1成功";}// 方法2:使用QDomDocumentif (writeXmlWithDomDocument("dom_document.xml")) {qDebug() << "方法2成功";}// 方法3:使用Qt XML Patternsif (writeXmlWithXmlPatterns("xml_patterns.xml")) {qDebug() << "方法3成功";}return a.exec();
}

最佳实践

  1. 文件安全写入

    • 使用QSaveFile而不是QFile,确保写入操作的原子性
    • 避免写入过程中断电导致文件损坏
  2. 编码处理

    // 确保使用UTF-8编码
    xml.writeStartDocument("1.0", true); // 第二个参数表示使用UTF-8
    
  3. 错误处理

    if (xml.hasError()) {qWarning() << "XML写入错误:" << xml.errorString();
    }
    
  4. 验证XML结构

    // 在开发阶段验证XML
    #include <QXmlSchemaValidator>bool validateXml(const QString &filename, const QString &schemaFile) {QXmlSchema schema;if (!schema.load(schemaFile)) return false;QXmlSchemaValidator validator(schema);return validator.validate(filename);
    }
    
  5. 性能优化

    • 对于大型文件,使用QXmlStreamWriter
    • 避免在循环中频繁打开/关闭文件
    • 使用缓存机制批量写入数据

生成的XML示例

<?xml version="1.0" encoding="UTF-8"?>
<Data version="1.0" created="2023-08-15T14:30:45Z"><!--这是一个使用QXmlStreamWriter生成的XML文件--><Books><Book id="1"><Title>Qt编程指南 1</Title><Author>作者 1</Author><Year>2016</Year><Price>36.5</Price><Description><![CDATA[<p>这是第1本书的描述,包含<strong>特殊字符</strong></p>]]></Description></Book><Book id="2"><Title>Qt编程指南 2</Title><Author>作者 2</Author><Year>2017</Year><Price>37.5</Price><Description><![CDATA[<p>这是第2本书的描述,包含<strong>特殊字符</strong></p>]]></Description></Book><Book id="3"><Title>Qt编程指南 3</Title><Author>作者 3</Author><Year>2018</Year><Price>38.5</Price><Description><![CDATA[<p>这是第3本书的描述,包含<strong>特殊字符</strong></p>]]></Description></Book></Books><Users><User id="1001" name="张三" role="管理员"/></Users>
</Data>

常见问题解决

  1. 中文乱码问题

    // 确保使用UTF-8编码
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    
  2. 文件权限问题

    // 设置正确的文件权限
    file.setPermissions(QFile::ReadOwner | QFile::WriteOwner);
    
  3. 特殊字符处理

    • 使用writeCDATA()处理包含特殊字符的内容
    • 或者使用QString::toHtmlEscaped()进行转义
  4. 大文件内存消耗

    • 使用QXmlStreamWriter代替QDomDocument
    • 分块写入XML文件

在Qt 5.9中,推荐使用QXmlStreamWriter配合QSaveFile进行XML文件写入,这种方法高效、安全且内存占用低,适合大多数应用场景。

http://www.lryc.cn/news/579155.html

相关文章:

  • JavaScript 性能优化实战:减少 DOM 操作引发的重排与重绘
  • 无人机一机多控技术的核心要点
  • 设计模式(八)
  • 【前端】1 小时实现 React 简历项目
  • 【Python】Python / PyCharm 虚拟环境详搭建与使用详解
  • MidJourney生成秦朝末年刘邦全身像提示词
  • RabbitMQ 高级特性之持久性
  • 二叉搜索树中第k小的元素
  • R Studio开发中记录
  • 【数据结构与算法】哈希表拾遗
  • Windows下docker安装
  • 前端下载xls文档乱码修复
  • Java学习第五部分——API部分
  • vue-36(为组件编写单元测试:属性、事件和方法)
  • Android15 开机动画播放结束之后如何直接启动应用
  • NVIDIA智能汽车技术公开课笔记
  • 胡兵全新时尚生活频道上线,开启多维生活美学新篇
  • 08_Excel 导入 - 用户信息批量导入
  • 【Erdas实验教程】024:遥感图像辐射增强(亮度反转Brightness Inversion)
  • 优雅草蜻蜓R实时音视频会议系统技术规划与全球RTC开源技术全景分析·优雅草卓伊凡|麻子|贝贝|clam
  • 远程问诊选声网视频通话,画面不卡音质更清楚
  • iOS重构期调试实战:架构升级中的性能与数据保障策略
  • 在mac下手动编译迁移的android版webrtc组件
  • Docker Dify安装 完整版本
  • 「Java流程控制」跳转语句
  • 【数据结构】排序算法:冒泡与快速
  • OWASP Top 10 是什么?
  • 胡兵创立时尚生活频道《HUBING SELECTS胡兵智选》担任主编深耕智选生活
  • java实现发送短信
  • QT6 源(147)模型视图架构里的表格窗体 QTableWidget 的范例代码举例,以及其条目 QTableWidgetItem 类型的源代码。