Qt之QDomDocument操作xml文件-模拟ini文件存储

时间:2022-12-22 19:59:14

一、背景

  不得不说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文件,需要的接口并不多,读、写、新增和删除。

Qt之QDomDocument操作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文件结构

Qt之QDomDocument操作xml文件-模拟ini文件存储

图2 xml文件操作头文件

1、读xml文件

 void xmlOperate::readXml( const QString & filePath )
{
if(filePath.isEmpty())
return; QFile file(filePath);
if(file.open(QFile::ReadOnly | QFile::Text) == false)
return; QDomDocument domDocument;
QString error;
int row = , column = ;
if(domDocument.setContent(&file, false, &error, &row, &column) == false)
return file.close(); if(domDocument.isNull())
return file.close(); m_mItemMap.clear(); QDomElement rootElement = domDocument.documentElement();
QDomNodeList groupList = rootElement.childNodes();
for(int i = ; i < groupList.count(); ++i)
{
QDomNode groupNode = groupList.item(i);
QDomElement groupElement = groupNode.toElement();
QString groupName = groupElement.attribute("name"); QMap<QString, QString> items;
QDomNodeList itemList = groupElement.childNodes();
for (int j = ; j < itemList.count(); ++j)
{
QDomNode itemNode = itemList.item(j);
QDomElement itemElement = itemNode.toElement();
QString itemName = itemElement.attribute("name");
QString itemText = itemElement.text(); if (itemName.isEmpty())
{
items[QString::number(j)] = itemText;
}
else
{
items[itemName] = itemText;
}
}
m_mItemMap[groupName] = items;
} file.close(); qDebug() << m_mItemMap;
}

2、保存xml文件

 void xmlOperate::writeXml(const QString & filePath)
{
QDomDocument domDocument;
QString strHeader( "version=\"1.0\" encoding=\"UTF-8\"" );
domDocument.appendChild( domDocument.createProcessingInstruction("xml", strHeader) ); QDomElement root = domDocument.createElement("groups");
domDocument.appendChild(root); for(auto iter = m_mItemMap.begin(); iter != m_mItemMap.end(); ++iter)
{
QDomElement groupNode = domDocument.createElement("group");
groupNode.setAttribute("name", iter.key()); QMap<QString, QString> items = iter.value();
for (auto iter2 = items.begin(); iter2 != items.end(); ++iter2)
{
QString key = iter2.key();
QString value = iter2.value(); QDomElement itemNode = domDocument.createElement("item");
itemNode.setAttribute("name", key); QDomText textNode = domDocument.createTextNode(value);
itemNode.appendChild(textNode); groupNode.appendChild(itemNode);
}
root.appendChild(groupNode);
} QFile file(filePath);
if(file.open(QFile::WriteOnly | QFile::Text))
{
QTextStream out(&file);
domDocument.save(out, );
file.close();
}
qDebug() << m_mItemMap;
}

3、插入项

 bool xmlOperate::addItem( const QString & value, const QString & group, const QString & key )
{
if (value.isEmpty() || group.isEmpty())
{
return false;
} if (key.isEmpty())
{
int count = m_mItemMap[group].size();
m_mItemMap[group][QString::number(count)] = value;
}
else
{
m_mItemMap[group][key] = value;
} writeXml(m_filePath); return true;
}

4、删除项

 bool xmlOperate::removeItem( const QString & value, const QString & group, const QString & key /*= ""*/ )
{
if (value.isEmpty() || group.isEmpty())
{
return false;
} if (key.isEmpty())
{
int count = m_mItemMap[group].size();
if (count == )
{
return false;
} auto iter = m_mItemMap[group].begin();
while (iter != m_mItemMap[group].end())
{
if (iter.value() == value)
{
iter = m_mItemMap[group].erase(iter);
}
else
{
++iter;
}
}
}
else
{
m_mItemMap[group].remove(key);
} writeXml(m_filePath); return true;
}

四、示例程序下载

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

Qt之QDomDocument操作xml文件-模拟ini文件存储

图3 测试程序结果

xml读写-xml模拟ini存储

Qt之QDomDocument操作xml文件-模拟ini文件存储的更多相关文章

  1. 怎么读取properties文件和ini文件?

    一.读取properties文件: properties中的内容: server.ip = 127.0.0.1 server.port = 22 //原生java即可读取public static v ...

  2. Qt读写ini文件

    一 背景 1 ini文件介绍 .ini 文件是Initialization File的缩写,即初始化文件. 除了windows现在很多其他操作系统下面的应用软件也有.ini文件,用来配置应用软件以实现 ...

  3. QT从入门到入土(三)——文件的读写操作

     引言 文件的读写是很多应用程序具有的功能,甚至某些应用程序就是围绕着某一种格式文件的处 理而开发的,所以文件读写是应用程序开发的一个基本功能. Qt 提供了两种读写纯文本文件的基本方法: 用 QFi ...

  4. C&num; ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  5. C&num;- 操作Ini文件

    以前习惯了使用.NET中的WEB.CONFIG或者APP.CONFIG,最近在做项目的时候遇到了些问题,发现没办法使用这些CONFIG文件.一开始我的做法是建一个文本文件,自己定规律,自己写方法去写新 ...

  6. 关于C&num;操作INI文件的总结

    原文:关于C#操作INI文件的总结   INI文件其实是一种具有特定结构的文本文件,它的构成分为三部分,结构如下: [Section1]key 1 = value2key 1 = value2--[S ...

  7. 读写ini文件

    C# 使用文件流来读写ini文件 背景 之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便.然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI ...

  8. Delphi INI 文件读写

    delphi中,配置文件的相关操作. () INI文件的结构: ;这是关于INI文件的注释部分 [节点] 关键字=值 ... INI文件允许有多个节点,每个节点又允许有多个关键字, “=”后面是该关键 ...

  9. INI文件,WritePrivateProfileString()和GetPrivateProfileString()函数----转载

    INI文件就是扩展名为“ini”的文件.在Windows系统中,INI文件是很多,最重要的就是“System.ini”.“System32.ini”和“Win.ini”.该文件主要存放用户所做的选择以 ...

随机推荐

  1. 实现跨浏览器html5表单验证

    div:nth-of-type(odd){ float: left; clear: left; } .origin-effect > div:nth-of-type(even){ float: ...

  2. 使用eclipse&plus;fiddler&plus;微信web开发者工具调试本地微信页面

    前面已经说了调试服务器上的微信页面,放链接:http://www.cnblogs.com/Gabriel-Wei/p/5977850.html 还有fiddler调试链接:http://www.cnb ...

  3. Python读取xml报错解析--ExpatError&colon; not well-formed &lpar;invalid token&rpar;

    xml文件内容如代码所示存入的名字为login.xml: <?xml version="1.0" encoding="utf-8"?> <in ...

  4. sign in和sign up区别

    如果是网站的话sign up是注册,sign in是登录的意思,另外,sign out退出

  5. 02&lowbar;Spring控制反转案例快速入门

    Spring控制反转案例快速入门 1.下载Spring最新开发包 http://www.springsource.org/download/community 下载spring3.2 的开发包 目录结 ...

  6. php的数组与字符串的转换函数整理

    1.将一个字符串转化为数组 str_split()用于将一个字符串转化为数组 语法: str_split(string,length) //string是必须的,是要分割的字符串: //length是 ...

  7. Android群英传笔记——第五章:Android Scroll分析

    Android群英传笔记--第五章:Android Scroll分析 滑动事件算是Android比较常用的效果了,而且滑动事件他本身也是有许多的知识点,今天,我们就一起来耍耍Scroll吧 一.滑动效 ...

  8. centos7&period;0 64位系统 安装PHP5&period;3 支持 nginx

    1  安装PHP所需要的扩展 yum -y install libxml2 libxml2-devel openssl openssl-devel bzip2 bzip2-devel curl cur ...

  9. Python标准库 -- UUID模块&lpar;生成唯一标识&rpar;

    UUID是什么: UUID: 通用唯一标识符 ( Universally Unique Identifier ),对于所有的UUID它可以保证在空间和时间上的唯一性,也称为GUID,全称为: UUID ...

  10. 解决点击cell执行动画导致的重用问题

    解决点击cell执行动画导致的重用问题 说明: 动画的细节都是裸露的,并没有封装,靠看官来优化了. 效果: 源码: https://github.com/YouXianMing/UITableView ...