技术笔记:Qt基础之配置文件(QSettings)

本文涉及的产品
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 技术笔记:Qt基础之配置文件(QSettings)

在项目开发中,配置文件通常分为三种:ini文件、xml文件和json文件,个人认为三种文件的区别在于:ini文件记录方便、格式简单但不便于扩展;xml文件和json文件扩展性强,能够记录更复杂的配置文件,但格式相对复杂,特别是对重复项的记录有优势。因此,在选择配置文件时,如文件内容较少,无(少)重复记录项,可选择ini文件,若文件内容多、逻辑层次复杂、需要重复记录多组数据或者后期后期可能需要扩展多层关系,可选择xml或json文件。


1.INI文件


Qt通过QSettings类读写ini文件(但是QSetting还可以读取其它类型的配置文件,例如:注册表)头文件:QSetting.h,QSetting读写ini文件的步骤为:


    通过路径名称打开文件并设定为ini文件格式


读/写数据


关闭文件,删除句柄


Qt读文件示例如下:


//打开文件并指定为ini格式


QSettings configIni = new QSettings(file_path, QSettings::IniFormat);


QString qTemp = "";


//读指定节点的指定数据,其中“Log”为节点,save_days为具体数据项


logDays = configIni->value("Log/save_days").toInt();


qTemp = configIni->value("Log/print_debug").toString();


printDbgLog = qTemp.compare("true", Qt::CaseInsensitive) == 0 ? true : false;


//删除指针,此处未关联父对象,必须手动删除,否则有内存泄露风险


delete configIni;


Qt写文件示例如下:


//打开文件


QSettings* configIni = new QSettings(filePath, QSettings::IniFormat);


QString qTemp = "";


//写入数据,必须指定写入节点和值


configIni->setValue("Public/remove_time", removeTime); //定时任务执行时间


configIni->setValue("Log/save_days", logDays); //日志保存天数


configIni->setValue("Log/print_debug", "true");


else


configIni->setValue("Log/print_debug", "false");


delete configIni;


2.XML文件


Qt有多种方法读取xml文件,有人在网上总结了几种方式,具体看这里,我使用的是DOM的方式,这种方式的有点在于理解简单,读写完全按照xml文件的层级操作即可;缺点则是需要将文件完全放入内存后才可读写,也就是说,对于非常大的xml文件,这不是一种理想的处理方式。使用DOM方式解析xml必须包含头文件:和


DOM方式读取xml文件的过程如下:


  a.读取文件内容并整体转换成DOM结构树存储于内存中;


  b.按结构解析节点数据;


  c.清理内存


  具体示例代码:


//xml类型配置文件读写


bool ConfigFile::LoadXMLFile(QString file_path)


{


bool bRet = true;


//step1:读文件


QFile file(file_path);


if (!file.open(QFile::ReadOnly))


{


errMsg = QString("文件打开失败,%1").arg(file.errorString());


return false;


}


QString errorStr;


int errorLine;


int errorColumn;


//qml数据存储格式


QDomDocument doc;


//step2:转换成xml数据格式


if (!doc.setContent(&file, false, &errorStr, &errorLine, &errorColumn))


{


errMsg = QString("QML解析错误,%1,%2,%3").arg(errorStr)


.arg(QString::number(errorLine)).arg(QString::number(errorColumn));


file.close();


return false;


}


//此时已经不需要文件句柄,可关闭


file.close();


//根节点元素


QDomElement //代码效果参考:http://www.jhylw.com.cn/163423697.html

root = doc.documentElement();

#pragma region "每个文件不一样,由此处开始修改"


//简单节点结构


QDomElement parts = root.firstChildElement("module");


if (parts.isNull())


{


bRet = false;


errMsg = "文件格式异常,未发现【module】节点";


goto _RET;


}


else


{


//ups


QDomElement temp = parts.firstChildElement("ups");


if (temp.isNull())


{


bRet = false;


errMsg = "文件格式异常,未发现【model/ups】节点";


goto _RET;


}


else


{


QString st = temp.text();


if (st.compare("true") == 0)


modeUPS = true;


else


modeUPS = false;


}


//多重嵌套、重复结构


{


parts = root.firstChildElement("processor_monitor");


if (parts.isNull())


{


bRet = false;


errMsg = QString("文件格式异常,未发现【processor_monitor】节点");


goto _RET;


}


else


{


//循环解析,获取测量点数据


QDomElement subElement = parts.firstChildElement();


while (!subElement.isNull())


{


if (subElement.tagName().compare("processor") == 0)


{


ProcessorInfo tempValue;


if (!GetProcessorInfo(subElement, tempValue))


{


bRet = false;


errMsg = QString("进程监控节点解析失败,%1").arg(errMsg);


goto _RET;


}


else


vecProcessorInfo.push_back(tempValue);


}


subElement = subElement.nextSiblingElement();


}


}


}


#pragma endregion


_RET:


doc.clear();


return bRet;


}


View Code


DOM方式写入xml文件的过程如下:


  a.创建DOM结构树根节点


  b.在根节点上按层级插入数据节点


  c.将内存中的DOM数据结构转化为符合xml格式的字符串


  d.将字符串写入文件


  具体示例代码:


bool ConfigFile::SaveXMLFile()


{


bool bRet = true;


QFile file(filePath);


QDomDocument doc; //xml结构


//以只写入方式打开,并且打开时清空原来内容


if (!file.open(QFile::WriteOnly | QFile::Truncate))


{


errMsg = QString("文件打开失败,%1").arg(file.errorString());


return false;


}


//写入xml头部


QDomProcessingInstruction instruction; //添加处理命令


instruction = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");


doc.appendChild(instruction);


//添加根节点


QDomElement root = doc.createElement("root");


doc.appendChild(root);


#pragma region 跟随配置文件记录项改变


QString strTemp = "";


QDomText text;


//写入model节点


{


//ups


QDomElement model = doc.createElement("module");


QDomElement subNode = doc.createElement("ups");


if (modeUPS)


strTemp = "true";


else


strTemp = "false";


text = doc.createTextNode(strTemp); //设置括号标签中间的值


subNode.appendChild(text);


model.appendChild(subNode);


//process


subNode = doc.createElement("process");


if (modeUPS)


strTemp = "true";


else


strTemp = "false";


text = doc.createTextNode(strTemp); //设置括号标签中间的值


subNode.appendChild(text);


model.appendChild(subNode);


root.appendChild(model);


}


//写入Processor_monitor节点数据


{


QDomElement eProcessorList = doc.createElement("processor_monitor");


for (auto it : vecProcessorInfo)


{


QDomElement eProcessor = doc.createElement("processor");


//name


QDomElement eSub = doc.createElement("name");


text = doc.createTextNode(it.processorName); //设置括号标签中间的值


eSub.appendChild(text);


eProcessor.appendChild(eSub);


//path


eSub = doc.createElement("path");


text = doc.createTextNode(it.processroPath); //设置括号标签中间的值


eSub.appendChild(text);


eProcessor.appendChild(eSub);


//autoStart


if (it.isRestart)


strTemp = "true";


else


strTemp = "false";


eSub = doc.createElement("autostart");


text = doc.createTextNode(strTemp); //设置括号标签中间的值


eSub.appendChild(text);


eProcessor.appendChild(eSub);


//property


strTemp = QString::number(it.stopProprity);


eSub = doc.createElement("proprity");


text = doc.createTextNode(strTemp); //设置括号标签中间的值


eSub.appendChild(text);


eProcessor.appendChild(eSub);


eProcessorList.appendChild(eProcessor);


}


root.appendChild(eProcessorList);


}


#pragma endregion


//输出到文件


QTextStream out_stream(&file);


doc.save(out_stream, 4); //缩进4格


file.close();


doc.clear()


return true;


}


View Code


DOM方式处理xml文件比较好理解:按照各个节点的实际从属关系插入/读取即可,但是对内存的使用效率偏低。


3.JSON文件


  在我的项目经验中,并没有碰到过用json文件作为配置文件的情况,个人理解,json多用于不同程序间的数据交互,相较与xml,它的冗余信息更少,但又不会丢失数据间逻辑关系,同时便于扩展,因此,个人认为,json数据更适合作为通信数据的载体而不是配置文件。


  Qt处理JSON数据的类为QJsonObject、QJsonDocument、QJsonValue、QJsonParseError,头文件与类名相同。JSON文件的处理与XML文件类似,读取文件的过程为:a.从文件读取数据;b.将字符型数据转换为JSON格式数据并存在内存;c.从内存结构中读取数据。写文件的过程为:a.创建内存结构;b.插入数据;c.将数据转化为字符型数据并存储到文本中。


以下代码展示了创建简单json数据的过程,最终结果QstrJson为QByteArray结构:


QJsonObject json;


json.insert("CMD", QString("GRM"));


json.insert("RM", macro_addr);


QJsonDocument document;


document.setObject(json);


QstrJson = document.toJson(QJsonDocument::Compact);


if (G_INIFILE->printDbgLog)


LOG(INFO) [ "发包数据:" [ QstrJson.toStdString();


以下代码展示解析简单json的过程,其中,原始数据保存在qstrRecv中


//解析数据


QJsonParseError parseJsonErr;


QJsonDocument document = QJsonDocument::fromJson(qstrRecv.toUtf8(), &parseJsonErr);


if (!(parseJsonErr.error == QJsonParseError::NoError))


{


errMsg = QString("解析json文件错误,%1").arg(parseJsonErr.errorString());


return false;


}


QJsonObject jsonObject = document.object();


//CMD


QString temp = jsonObject【"CMD"】.toString();


if (temp.compare("GRM") != 0)


{


errMsg = "收包命令错误";


return false;


}


//RM


int addrIn = jsonObject【"RM"】.toInt();


if (addrIn != macro_addr)


{


errMsg = "收包Macro地址错误";


return false;


}


//RET


if (jsonObject.contains("RET"))


{


QJsonValue jsonValueList <

相关文章
|
1月前
|
Web App开发 编解码 安全
视频会议技术 入门探究:WebRTC、Qt与FFmpeg在视频编解码中的应用
视频会议技术 入门探究:WebRTC、Qt与FFmpeg在视频编解码中的应用
285 4
|
1月前
【QT】读写.ini配置文件的程序实现
【QT】读写.ini配置文件的程序实现
|
1月前
|
Linux 数据处理 C++
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(一)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
116 0
|
1月前
|
存储 Linux API
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(三)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
57 1
|
1月前
|
消息中间件 Linux 数据处理
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用(二)
Linux系统编程 C/C++ 以及Qt 中的零拷贝技术: 从底层原理到高级应用
68 1
|
8月前
|
存储 编译器 数据库
[笔记]OpenCV+FFmpeg+Qt实现视频编辑器之OpenCV核心类型 Mat
[笔记]OpenCV+FFmpeg+Qt实现视频编辑器之OpenCV核心类型 Mat
|
3天前
|
调度
技术笔记:QT之深入理解QThread
技术笔记:QT之深入理解QThread
|
1月前
|
编解码 供应链 开发工具
英飞凌采用Qt图形解决方案增强Traveo T2G MCU系列,实现智能渲染技术
在竞争激烈的全球半导体市场,制造商一直在努力缩短产品上市时间。同时,他们对流畅、高分辨率图形显示器的需求也在日益增长。
|
8月前
|
计算机视觉
[笔记]OpenCV+FFmpeg+Qt实现视频编辑器之OpenCV视频lO接口
[笔记]OpenCV+FFmpeg+Qt实现视频编辑器之OpenCV视频lO接口
128 0
|
8月前
|
文字识别 算法 计算机视觉
[笔记]OpenCV+FFmpeg+Qt实现视频编辑器之OpenCV图像处理
[笔记]OpenCV+FFmpeg+Qt实现视频编辑器之OpenCV图像处理
119 1

推荐镜像

更多