新鲜出炉啊,紧跟上一章,本次主要讲下json和xml这两种格式的解析,冲冲冲
Json文件读取与写入
🚩🚩🚩
json格式依赖的头文件就比较多了,谁让人家结构复杂呢
#include <QFile> //不是必须的,但是涉及到文件的读取,所以我就用到了
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
- 话不多说,让我们看看他的头文件和CPP文件都长什么样子
🍎🍎
/**
* @Brief: json文件读取,这里制定读取key对应的value,value为字符串
* @Author: springIce
* @Date: 2024-02-06
**/
static QString jsonFileRead(const QString &filePath, const QString &key);
/**
* @Brief: json文件写入,这里只拿一组进行举例,其实该操作更多的用在网络请求中组装json数据字段
* @Author: springIce
* @Date: 2024-02-06
**/
static bool jsonFileWrite(const QString &filePath, const QString &key, const QString &value);
- 还是依照惯例,我将其声明为静态函数,调用方便些
🍉🍉
QString FileUtils::jsonFileRead(const QString &filePath, const QString &key)
{
if (filePath.isEmpty()) {
qDebug() << "filePath is empty";
return "";
}
//读取文件的内容
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return "";
}
QByteArray jsonData = file.readAll();
file.close();
//开始解析
QJsonParseError parserError;
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData, &parserError);
if (jsonDoc.isNull()) {
qDebug() << parserError.errorString();
return "";
}
//{{}, {}} 这里只是用一层机构进行举例,如果包含多层则多层判断即可
if (jsonDoc.isObject()) {
QJsonObject jsonObj = jsonDoc.object();
QJsonValue value = jsonObj.value(key);
if (value.isString()) {
return value.toString();
}
// ... 处理其他数据类型
return "";
}
//[{}, {}, {}]
if (jsonDoc.isArray()) {
QJsonArray jsonArray = jsonDoc.array();
for (const QJsonValue &value : jsonArray) {
if (value.isObject()) {
QJsonObject jsonObject = value.toObject();
QJsonValue value = jsonObject.value(key);
if (value.isString()) {
return value.toString();
}
// ... 处理其他数据类型
}
}
}
return "";
}
bool FileUtils::jsonFileWrite(const QString &filePath, const QString &key, const QString &value)
{
if (filePath.isEmpty() || key.isEmpty() || value.isEmpty()) {
qDebug() << "necessary params are empty";
return false;
}
// 创建一个 JSON 对象
QJsonObject jsonObject;
jsonObject[key] = value;
// 创建一个 JSON 数组
QJsonArray jsonArray;
jsonArray.append(jsonObject); // 将 JSON 对象添加到数组中
// 创建一个 JSON 文档并将数组设置为其内容
QJsonDocument jsonDoc(jsonArray);
// 将 JSON 文档转换为字符串
QString jsonString = jsonDoc.toJson(QJsonDocument::Indented); // 格式化输出
// 写入文件
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
out << jsonString;
file.close();
return true;
}
qDebug() << "Cannot open file for writing";
return false;
}
具体实现就有点长了,虽然代码里面也有注释,但我还是提几点:
1、尽可能的少写条件套条件的代码(if {if{if {}}}),能return就return,整体看起来也会简洁,逻辑也十分清晰;要不然谁来了都头大😂😂😂
2、字里行间缩进一定要保持好的习惯,当然qt有快捷键直接帮助你调整文件格式ctrl+i
3、其实也不难理解,QJsonDocument将数据流转化为json格式;QJsonObject json中被大括号括起来的部分;QJsonArray json中被中括号括起来的部分;然后根据你自己的格式文件进行组合就好了
- 那就看调用和效果吧🍭🍭
QString iniFilePath = "E:\\Qt\\Project\\Logout\\testFile\\myIniFile.json";
FileUtils::jsonFileWrite(iniFilePath, "Custom", "you_are_right");
qDebug() << FileUtils::jsonFileRead(iniFilePath, "Custom");
- json文件不存在的话会自动新建,无需担心
Xml文件读取与写入
🚩🚩🚩
- 先看看他需要依赖那些头文件
!!!!别忘了去pro文件里面添加依赖啊
QT += xml
#include <QDomDocument>
#include <QDomElement>
那就直接开搞,声明实现通通来吧
🍎🍎
/**
* @Brief: xml文件读写,没有对输入进行封装,这里我是写死的节点key,可以自行修改
* @Author: springIce
* @Date: 2024-02-06
**/
static void xmlFileRead(const QString &filePath);
static bool xmlFileWrite(const QString &filePath);
🍉🍉
/*
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Alice</to>
<from>Bob</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
*/
void FileUtils::xmlFileRead(const QString &filePath)
{
if (filePath.isEmpty()) {
qDebug() << "filePath is empty";
return;
}
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "Cannot open file";
return;
}
QDomDocument doc;
QString errMsg;
if (!doc.setContent(&file, &errMsg)) {
file.close();
qWarning() << errMsg;
return;
}
file.close();
QDomElement root = doc.documentElement();
if (root.tagName() != "note") {
qWarning() << "root tagname is unequal";
return;
}
QDomNodeList items = root.childNodes();
for (int i = 0; i < items.count(); ++i) {
QDomNode itemNode = items.at(i);
if (itemNode.isElement()) {
QDomElement itemElement = itemNode.toElement();
qDebug() << "Element:" << itemElement.tagName()
<< "Content:" << itemElement.text();
}
}
}
bool FileUtils::xmlFileWrite(const QString &filePath)
{
if (filePath.isEmpty()) {
qDebug() << "filePath is empty";
return false;
}
QDomDocument doc;
QDomElement note = doc.createElement("note");
doc.appendChild(note);
QDomElement to = doc.createElement("to");
to.appendChild(doc.createTextNode("Alice"));
note.appendChild(to);
QDomElement from = doc.createElement("from");
from.appendChild(doc.createTextNode("Bob"));
note.appendChild(from);
QDomElement heading = doc.createElement("heading");
heading.appendChild(doc.createTextNode("Reminder"));
note.appendChild(heading);
QDomElement body = doc.createElement("body");
body.appendChild(doc.createTextNode("Don't forget the meeting!"));
note.appendChild(body);
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
qDebug() << "Cannot open file";
return false;
}
QTextStream stream(&file);
doc.save(stream, 4); // 4 是缩进宽度
file.close();
return true;
}
那就简单说两句:
第一决不能意气用事… 好好好,串场了是吧
再来
1、我这里呢,只是以最简单的方式给一个例子,里面的key啥的都是写死的,你可以进行入参封装,然后对传入的参数进行自己的解析就好;
2、其实写代码是为了具体实现功能,但是整洁、清晰的代码谁又能拒绝呢;
3、纵观第五弹前后两章内容,其实我有一个地方写的冗余了(猜猜看,猜到了你就又进一步),一定要记得公共部分就提取出来,没必要一直去重复的复制粘贴,无意义啊
好了,到最后了,第六弹会是什么内容呢,会不会有人期待啊。不管了,我先站自己一票,让我们尽情期待吧🙉🙉🙉