zoukankan      html  css  js  c++  java
  • Qt之QDomDocument操作xml文件-模拟ini文件存储

    一、背景

      不得不说Qt是一个很强大的类库,不管是做项目还是做产品,Qt自身封装的东西就已经非常全面了,我们今天的这篇文章就是模拟了Qt读写ini文件的一个操作,当然是由于一些外力原因,我们决定自己来完善下这个功能。好的,那么现在就让我们隆重的请出今天的主角--QSettings。这个类能干嘛呢? 答案就是:读写注册表或者读写ini文件,这对于我们做应用程序时记录一些可持久化数据非常有用。

    二、QSettings访问ini文件

      QSettings访问ini文件相对来说比较简单,我们只需要构造一个QSettings对象,传入文件名称和文件存储格式即可,如图1所示。但同时QSettings也有一些局限,如下:
    1、QSettings的编码问题(QTBUG15543、QTBUG19552)
    2、QSettings的key不能为中文
    3、当在一个嵌套作用域多次构造QSettings时并设置了编码,此时访问文件设置的编码会失效
      由于QSettings有一些限制,也就引出了我们这篇文章的内容,使用xml模拟ini文件,下面我们主要分析下怎么使用xml文件模拟ini文件,需要的接口并不多,读、写、新增和删除。

    图1 QSettings读写ini

    三、xml文件读写

      读写xml文件的方式有很多,Qt提供了2种比较常用的方式:DOM和SAX,详情可以参看:Qt学习之XML读写操作小结。初次之外C++还提供了几种库用于操作xml文件,比如:libxml2、tinyXml等。
    此处我们模拟的是QSettings读写ini文件,因此使用Qt自带的DOM方式读写xml,操作起来相对容易。

      如图2所示,是我们xml文件操作类的几个重要接口和成员,前边4个公有接口分别对应。读、写、新增和删除;成员变量m_filePath表示加载的xml文件路径,m_mItemMap表示2级的ini文件结构

    图2 xml文件操作头文件

    1、读xml文件

     1 void xmlOperate::readXml( const QString & filePath )
     2 {
     3     if(filePath.isEmpty())
     4         return;
     5 
     6     QFile file(filePath);
     7     if(file.open(QFile::ReadOnly | QFile::Text) == false)
     8         return;
     9 
    10     QDomDocument domDocument;
    11     QString error;
    12     int row = 0, column = 0;
    13     if(domDocument.setContent(&file, false, &error, &row, &column) == false)
    14         return file.close();
    15 
    16     if(domDocument.isNull()) 
    17         return file.close();
    18 
    19     m_mItemMap.clear();
    20 
    21     QDomElement rootElement = domDocument.documentElement();
    22     QDomNodeList groupList = rootElement.childNodes();
    23     for(int i = 0; i < groupList.count(); ++i)
    24     {
    25         QDomNode groupNode = groupList.item(i);
    26         QDomElement groupElement = groupNode.toElement();
    27         QString groupName = groupElement.attribute("name");
    28 
    29         QMap<QString, QString> items;
    30         QDomNodeList itemList = groupElement.childNodes();
    31         for (int j = 0; j < itemList.count(); ++j)
    32         {
    33             QDomNode itemNode = itemList.item(j);
    34             QDomElement itemElement = itemNode.toElement();
    35             QString itemName = itemElement.attribute("name");
    36             QString itemText = itemElement.text();
    37 
    38             if (itemName.isEmpty())
    39             {
    40                 items[QString::number(j)] = itemText;
    41             }
    42             else
    43             {
    44                 items[itemName] = itemText;
    45             }
    46         }
    47         m_mItemMap[groupName] = items;
    48     }
    49 
    50     file.close();
    51 
    52     qDebug() << m_mItemMap;
    53 }
    View Code

    2、保存xml文件

     1 void xmlOperate::writeXml(const QString & filePath)
     2 {
     3     QDomDocument domDocument;
     4     QString strHeader( "version="1.0" encoding="UTF-8"" );
     5     domDocument.appendChild( domDocument.createProcessingInstruction("xml", strHeader) );
     6 
     7     QDomElement root = domDocument.createElement("groups");
     8     domDocument.appendChild(root);
     9 
    10     for(auto iter = m_mItemMap.begin(); iter != m_mItemMap.end(); ++iter)
    11     {
    12         QDomElement groupNode = domDocument.createElement("group");
    13         groupNode.setAttribute("name", iter.key());
    14 
    15         QMap<QString, QString> items = iter.value();
    16         for (auto iter2 = items.begin(); iter2 != items.end(); ++iter2)
    17         {
    18             QString key = iter2.key();
    19             QString value = iter2.value();
    20 
    21             QDomElement itemNode = domDocument.createElement("item");
    22             itemNode.setAttribute("name", key);
    23 
    24             QDomText textNode = domDocument.createTextNode(value);
    25             itemNode.appendChild(textNode);
    26 
    27             groupNode.appendChild(itemNode);
    28         }
    29         root.appendChild(groupNode);
    30     }
    31 
    32     QFile file(filePath);
    33     if(file.open(QFile::WriteOnly | QFile::Text))
    34     {
    35         QTextStream out(&file);
    36         domDocument.save(out, 4);
    37         file.close();
    38     }
    39     qDebug() << m_mItemMap;
    40 }
    View Code

    3、插入项

     1 bool xmlOperate::addItem( const QString & value, const QString & group, const QString & key )
     2 {
     3     if (value.isEmpty() || group.isEmpty())
     4     {
     5         return false;
     6     }
     7 
     8     if (key.isEmpty())
     9     {
    10         int count = m_mItemMap[group].size();
    11         m_mItemMap[group][QString::number(count)] = value;
    12     }
    13     else
    14     {
    15         m_mItemMap[group][key] = value;
    16     }
    17 
    18     writeXml(m_filePath);
    19 
    20     return true;
    21 }

    4、删除项

     1 bool xmlOperate::removeItem( const QString & value, const QString & group, const QString & key /*= ""*/ )
     2 {
     3     if (value.isEmpty() || group.isEmpty())
     4     {
     5         return false;
     6     }
     7 
     8     if (key.isEmpty())
     9     {
    10         int count = m_mItemMap[group].size();
    11         if (count == 0)
    12         {
    13             return false;
    14         }
    15         
    16         auto iter = m_mItemMap[group].begin();
    17         while (iter != m_mItemMap[group].end())
    18         {
    19             if (iter.value() == value)
    20             {
    21                 iter = m_mItemMap[group].erase(iter);
    22             }
    23             else
    24             {
    25                 ++iter; 
    26             }
    27         }
    28     }
    29     else
    30     {
    31         m_mItemMap[group].remove(key);
    32     }
    33 
    34     writeXml(m_filePath);
    35 
    36     return true;
    37 }

    四、示例程序下载

    如图3是测试代码生成的测试结果,group相当于ini文件中的一个分组,item表示分组中的一项

    图3 测试程序结果

    xml读写-xml模拟ini存储

  • 相关阅读:
    python正则去掉html标签里的css内容
    elasticsearch scroll
    js控制滚动条自动往下滑动
    Pandas导出Excel的时候出现openpyxl.utils.exceptions.IllegalCharacterError异常问题
    C# 动态构建表达式树(二)——构建 Select 和 GroupBy 的表达式
    C# 动态构建表达式树(一)—— 构建 Where 的 Lambda 表达式
    C# 中 async 和 await 的基本使用
    C# 中 AppDomain 的一些理解
    win10家庭版 无法修改hosts文件
    我的第一个Scala程序
  • 原文地址:https://www.cnblogs.com/swarmbees/p/9305272.html
Copyright © 2011-2022 走看看