赞
踩
最近做了一个基于Qt的对于.xml文件和.ini文件的写入和读取项目(Qt版本为5.12.10).在输入框中输入数据,点击确认按钮,选择是否修改配置文件,然后选择对应的文件类型(xml或者ini文件),即可将数据写入配置文件。Qt 的UI界面如下所示:
下面是项目的源代码展示,包含四个内容:
QT += core gui QT += xml greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ readandwritefile.cpp HEADERS += \ readandwritefile.h FORMS += \ readandwritefile.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
#ifndef READANDWRITEFILE_H #define READANDWRITEFILE_H /******************************************** * @headerfile: readandwritefile.h * @brief: 声明了ReadandWriteFile类,该类用于读取和写入文件。 * 包含了一些与文件处理相关的方法和槽函数。 * @author: Jacky Zou * @date: 2023-07-31 *********************************************/ #include <QFile> #include <QDomNodeList> #include <QMainWindow> namespace Ui { class ReadandWriteFile; } // namespace Ui class ReadandWriteFile : public QMainWindow { Q_OBJECT public: /** * @brief ReadandWriteFile类的构造函数。 * @param parent 父级窗口的指针,默认为nullptr。 */ explicit ReadandWriteFile(QWidget *parent = nullptr); ~ReadandWriteFile(); // ReadandWriteFile类的析构函数。 public: void writeXml(); // 写入xml数据到xml文件 void readXml(); // 读取xml文件 bool openXml(QString &fileNamePath_); // 打开xml文件 void readRootXml(QDomNodeList &sonNodeLists_); // 处理子节点集 static void iniDataWrite(const QString& filename, Ui::ReadandWriteFile *ui); // 静态方法写入ini文件 static void iniDataRead(const QString& filename); // 静态方法读取ini文件 private slots: void on_readBtn_clicked(); // 读取按钮的槽函数 void on_cancelBtn_clicked(); // 取消按钮的槽函数 void on_writeBtn_clicked(); // 确认(写入)按钮的槽函数 private: Ui::ReadandWriteFile *ui; QFile xml_file; // 创建对象 QString currentXmlFilePath_; // 当前xml文件路径 QString currentIniFilePath_; // 当前Ini文件路径 QString currentXmlFileName_; // 当前xml文件名 QString currentIniFileName_; // 当前ini文件名 QVector<QString> inputData_; // 用户输入的数据 }; #endif // READANDWRITEFILE_H
#include "readandwritefile.h" #include "ui_readandwritefile.h" #include <QDebug> #include <QDomDocument> #include <QSettings> #include <QMessageBox> #include <QRegExpValidator> #include <QTextCodec> /********************************************** * @projectName ReadandWriteFile * @brief ReadandWriteFile类的构造函数。 * @param parent 父级窗口的指针,默认为nullptr。 * @details 构造函数用于初始化ReadandWriteFile对象,并设置界面的初始状态。 * 在构造函数中,设置了输入框的验证器,以限制输入数据库IP和端口号的格式。 * 还初始化了当前xml文件路径、当前ini文件路径以及xml和ini配置文件的名称。 * @author Jacky Zou * @date 2023-07-31 **********************************************/ ReadandWriteFile::ReadandWriteFile(QWidget *parent) : QMainWindow(parent) , ui(new Ui::ReadandWriteFile) { ui->setupUi(this); // 使用IPv4地址的正则表达式来限制输入数据库IP QString dbIP = "\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"; ui->lineEdit->setValidator(new QRegExpValidator(QRegExp(dbIP))); ui->lineEdit->setInputMask("000.000.000.000"); // 使用正则表达式限制输入数据库端口号 QString portNum = "^([0-9]|[1-9]\\d|[1-9]\\d{2}|[1-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$"; ui->lineEdit_5->setValidator(new QRegExpValidator(QRegExp(portNum))); currentXmlFilePath_ = QCoreApplication::applicationDirPath(); // 当前xml文件路径 currentIniFilePath_ = QCoreApplication::applicationDirPath(); // 当前Ini文件路径 currentXmlFileName_ = "/database.xml"; // xml配置文件名称 currentIniFileName_ = "/database.ini"; // ini配置文件名称 } // ReadandWriteFile类的析构函数。 ReadandWriteFile::~ReadandWriteFile() { delete ui; } /********************************************** * @projectName ReadandWriteFile * @brief 写入xml文件 * @param void * @return void * @author Jacky Zou * @date 2023-07-31 **********************************************/ void ReadandWriteFile::writeXml() { // 判断文件是否存在 if (QFile::exists(currentXmlFilePath_ + currentXmlFileName_)) { QFile::remove(currentXmlFilePath_ + currentXmlFileName_); // 删除文件 } // 文件存在则创建,否则创建一个文件 if(!openXml(currentXmlFileName_)) { qDebug() << qPrintable("写入时,打开文件失败"); return; } QDomDocument domDoc; // 创建xml类 QDomProcessingInstruction version; // 创建xml处理类,通常用于处理第一行描述信息 version = domDoc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\""); // 创建xml头部格式 domDoc.appendChild(version); // 添加到xml文件 QDomElement domRootElement = domDoc.createElement("XMLConfigFile"); // 创建xml文件根节点 domDoc.appendChild(domRootElement); QDomElement fatherNodeElement = domDoc.createElement("admin"); // 创建父节点 domRootElement.appendChild(fatherNodeElement); // 添加关系,将父节点挂到根节点 QDomElement sonNode1 = domDoc.createElement("DBIP"); // 创建子节点 QDomText sonText1 = domDoc.createTextNode("数据库IP:" + ui->lineEdit->text()); // 设置尖括号中的值 // 添加关系,将子节点挂至父节点 sonNode1.appendChild(sonText1); fatherNodeElement.appendChild(sonNode1); QDomElement sonNode2 = domDoc.createElement("PortNumber"); // 创建子节点 QDomText sonText2 = domDoc.createTextNode("数据库端口号:" + ui->lineEdit_5->text()); // 设置尖括号中的值 // 添加关系,将子节点挂至父节点 sonNode2.appendChild(sonText2); fatherNodeElement.appendChild(sonNode2); QDomElement sonNode3 = domDoc.createElement("DriverName"); // 创建子节点 QDomText sonText3 = domDoc.createTextNode("驱动名称:" + ui->lineEdit_2->text()); // 设置尖括号中的值 // 添加关系,将子节点挂至父节点 sonNode3.appendChild(sonText3); fatherNodeElement.appendChild(sonNode3); QDomElement sonNode4 = domDoc.createElement("DBName"); // 创建子节点 QDomText sonText4 = domDoc.createTextNode("数据库名:" + ui->lineEdit_6->text()); // 设置尖括号中的值 // 添加关系,将子节点挂至父节点 sonNode4.appendChild(sonText4); fatherNodeElement.appendChild(sonNode4); QDomElement sonNode5 = domDoc.createElement("UserName"); // 创建子节点 QDomText sonText5 = domDoc.createTextNode("用户名:" + ui->lineEdit_3->text()); // 设置尖括号中的值 // 添加关系,将子节点挂至父节点 sonNode5.appendChild(sonText5); fatherNodeElement.appendChild(sonNode5); QDomElement sonNode6 = domDoc.createElement("Password"); // 创建子节点 QDomText sonText6 = domDoc.createTextNode("密码:" + ui->lineEdit_4->text()); // 设置尖括号中的值 // 添加关系,将子节点挂至父节点 sonNode6.appendChild(sonText6); fatherNodeElement.appendChild(sonNode6); // 将其写入到xml文件中 QTextStream stream(&xml_file); domDoc.save(stream, 4); // 缩进四格 xml_file.close(); } /********************************************** * @projectName ReadandWriteFile * @brief 读取xml文件 * @param void * @return void * @author Jacky Zou * @date 2023-07-31 **********************************************/ void ReadandWriteFile::readXml() { // 打开或创建文件 if(!openXml(currentXmlFileName_)) { qDebug() << qPrintable("读取时,打开文件失败"); return; } QDomDocument doc; // 设置变量定位xml文件中出错的地方 int errLine = -1; int errColum = -1; QString strError = ""; if(!doc.setContent(&xml_file, true, &strError, &errLine, &errColum)) { qDebug() << strError << "line: " << errLine << "colum: " << errColum; // 打印报错位置 xml_file.close(); qDebug() << qPrintable("读取xml文件失败"); return; } xml_file.close(); // 关闭之前打开的文件,释放文件资源,并确保文件的写入操作已完成。 QDomElement root = doc.documentElement(); // 返回根节点 QDomNode node = root.firstChild(); // 获得第一个子节点 while (!node.isNull()) { // 遍历节点 QDomNodeList nodelists = node.childNodes(); // 获取当前节点的子节点列表 QString root = node.toElement().tagName(); // 获取当前节点的标签名 if(root == "admin") { readRootXml(nodelists); // 调用readRootXml节点匹配函数,读取并打印输出 } node = node.nextSibling(); // 读取下一个兄弟节点 } } /********************************************** * @projectName ReadandWriteFile * @brief 读取每个节点,判断每个节点的标签名, * 若标签名匹配,则打印该节点的文本内容 * @param sonNodeLists_ 子节点列表 * @return void * @author Jacky Zou * @date 2023-07-31 **********************************************/ void ReadandWriteFile::readRootXml(QDomNodeList &sonNodeLists_) { for (int i = 0; i < sonNodeLists_.size(); i++) { QDomElement sonElement = sonNodeLists_.at(i).toElement(); if(sonElement.toElement().tagName().compare("DBIP") == 0) { qDebug() << qPrintable(sonElement.text()); // qPrintable()用于去除打印结果的双引号 } else if (sonElement.toElement().tagName().compare("PortNumber") == 0) { qDebug() << qPrintable(sonElement.text()); } else if (sonElement.toElement().tagName().compare("DriverName") == 0) { qDebug() << qPrintable(sonElement.text()); } else if (sonElement.toElement().tagName().compare("DBName") == 0) { qDebug() << qPrintable(sonElement.text()); } else if (sonElement.toElement().tagName().compare("UserName") == 0) { qDebug() << qPrintable(sonElement.text()); } else if (sonElement.toElement().tagName().compare("Password") == 0) { qDebug() << qPrintable(sonElement.text()); } } } // 打开xml文件,并返回打开操作的结果(成功或失败) bool ReadandWriteFile::openXml(QString &fileNamePath_) { xml_file.setFileName(currentXmlFilePath_ + "./" + fileNamePath_); return xml_file.open(QIODevice::ReadWrite | QFile::Text); // 调用xml_file的open函数以读写模式打开文件 } /********************************************** * @projectName ReadandWriteFile * @brief 将数据写入ini文件 * @param filename 文件名 * @param ui UI对象指针 * @return void * @author Jacky Zou * @date 2023-07-31 **********************************************/ void ReadandWriteFile::iniDataWrite(const QString& filename, Ui::ReadandWriteFile *ui) { QString filePath = QCoreApplication::applicationDirPath()+ "./" + filename; // 写入路径 QSettings settings(filePath, QSettings::IniFormat); // 使用`QSettings`直接打开ini文件,并将数据写入其中 // 设置ini文件的编码为UTF-8 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); settings.setIniCodec(codec); // 写入配置信息 QString value1 = QString("数据库IP:") + ui->lineEdit->text(); // 获取数据库IP编辑框的文本 QString value2 = QString("驱动名称:") + ui->lineEdit_2->text(); // 获取驱动名称编辑框的文本 QString value3 = QString("用户名:") + ui->lineEdit_3->text(); // 获取用户名编辑框的文本 QString value4 = QString("密码:") + ui->lineEdit_4->text(); // 获取密码编辑框的文本 QString value5 = QString("数据库端口号:") + ui->lineEdit_5->text(); // 获取数据库端口号编辑框的文本 QString value6 = QString("数据库名:") + ui->lineEdit_6->text(); // 获取数据库名编辑框的文本 // 将键(key)和值(value)写入ini文件的节(section)中 settings.setValue(QString("Section1/Key1"), value1); settings.setValue(QString("Section2/Key2"), value2); settings.setValue(QString("Section3/Key3"), value3); settings.setValue(QString("Section4/Key4"), value4); settings.setValue(QString("Section5/Key5"), value5); settings.setValue(QString("Section6/Key6"), value6); // 写入ini文件后检查是否发生了错误,并打印错误信息 if (settings.status() != QSettings::NoError) { qDebug() << qPrintable("写入文件时发生错误:") << settings.status(); } settings.sync(); // 将内存中的设置同步到硬盘上的配置文件中 } /********************************************** * @projectName ReadandWriteFile * @brief 从ini文件中读取数据 * @param filename 文件名 * @return void * @author Jacky Zou * @date 2023-07-31 **********************************************/ void ReadandWriteFile::iniDataRead(const QString& filename) { QString filePath = QCoreApplication::applicationDirPath()+ "./" + filename; // 读取路径 QSettings settings(filePath, QSettings::IniFormat); // 使用`QSettings`直接打开ini文件,并读取其中的数据 // 设置ini文件的编码为UTF-8 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); settings.setIniCodec(codec); // 读取配置信息 // 从ini文件的节(section)中读取键(key)的值 QString value1 = settings.value("Section1/Key1").toString(); QString value2 = settings.value("Section2/Key2").toString(); QString value3 = settings.value("Section3/Key3").toString(); QString value4 = settings.value("Section4/Key4").toString(); QString value5 = settings.value("Section5/Key5").toString(); QString value6 = settings.value("Section6/Key6").toString(); // 在qDebug()中显示读取的配置信息 qDebug() << qPrintable(value1); qDebug() << qPrintable(value2); qDebug() << qPrintable(value3); qDebug() << qPrintable(value4); qDebug() << qPrintable(value5); qDebug() << qPrintable(value6); // 读取ini文件后检查是否发生了错误,并打印错误信息 if (settings.status() != QSettings::NoError) { qDebug() << qPrintable("读取文件时发生错误:") << settings.status(); } } // 读取按钮的槽函数 void ReadandWriteFile::on_readBtn_clicked() { // 将QMessageBox的 “Yes” 按钮 改为 “是”, “No” 改为 “否” QMessageBox confirm(QMessageBox::Question, tr("将要读取配置文件"), tr("是否确认读取?"), QMessageBox::Yes | QMessageBox::No); confirm.setButtonText(QMessageBox::Yes, tr("是")); confirm.setButtonText(QMessageBox::No, tr("否")); int choose = confirm.exec(); // 如果选择“是”,则进行下一步 if(choose == QMessageBox::Yes) { QMessageBox whichFileType(QMessageBox::Question, tr("选择文件类型"), tr("选择要读取哪种文件?"), QMessageBox::Yes | QMessageBox::No); whichFileType.setButtonText(QMessageBox::Yes, tr("xml")); whichFileType.setButtonText(QMessageBox::No, tr("ini")); int fileType = whichFileType.exec(); // 如果确认读取配置文件,接下来选择要读取哪种文件,xml或ini if(fileType == QMessageBox::Yes) { qDebug() << qPrintable("读取xml文件成功"); qDebug() << qPrintable("当前读取文件路径:") << currentXmlFilePath_ + currentXmlFileName_; qDebug() << qPrintable("读取文件内容如下:"); readXml(); // 调用xml读取函数 } else if(fileType == QMessageBox::No) { qDebug() << qPrintable("读取ini文件成功"); qDebug() << qPrintable("当前读取文件路径:") << currentIniFilePath_ + currentIniFileName_; qDebug() << qPrintable("读取文件内容如下:"); iniDataRead(currentIniFileName_); // 调用ini读取函数 } return; } } // 取消按钮的槽函数 void ReadandWriteFile::on_cancelBtn_clicked() { this->close(); // 关闭当前窗口 } // 确认(写入)按钮的槽函数 void ReadandWriteFile::on_writeBtn_clicked() { // 将QMessageBox的 “Yes” 按钮 改为 “是”, “No” 改为 “否” QMessageBox confirm(QMessageBox::Question, tr("将要修改配置文件"), tr("是否确认修改?"), QMessageBox::Yes | QMessageBox::No); confirm.setButtonText(QMessageBox::Yes, tr("是")); confirm.setButtonText(QMessageBox::No, tr("否")); int choose = confirm.exec(); // 如果选择“是”,则进行下一步 if(choose == QMessageBox::Yes) { QMessageBox whichFileType(QMessageBox::Question, tr("选择文件类型"), tr("选择要修改哪种文件?"), QMessageBox::Yes | QMessageBox::No); whichFileType.setButtonText(QMessageBox::Yes, tr("xml")); whichFileType.setButtonText(QMessageBox::No, tr("ini")); int fileType = whichFileType.exec(); // 如果确认修改配置文件,接下来选择要修改哪种文件,xml或ini if(fileType == QMessageBox::Yes) { writeXml(); // 调用xml写入函数 qDebug() << qPrintable("写入xml文件成功"); qDebug() << qPrintable("当前写入文件路径:") << currentXmlFilePath_ + currentXmlFileName_; } else if(fileType == QMessageBox::No) { iniDataWrite(currentIniFileName_, ui); // 调用ini写入函数 qDebug() << qPrintable("写入ini文件成功"); qDebug() << qPrintable("当前写入文件路径:") << currentIniFilePath_ + currentIniFileName_; } return; } }
#include "readandwritefile.h" #include <QApplication> #include <QTextCodec> int main(int argc, char *argv[]) { QApplication a(argc, argv); ReadandWriteFile w; w.show(); //设置中文编码,防止编码格式的问题导致乱码 #if (QT_VERSION <= QT_VERSION_CHECK(5,0,0)) #if _MSC_VER // 使用GBK编码 QTextCodec *codec = QTextCodec::codecForName("GBK"); #else QTextCodec *codec = QTextCodec::codecForName("UTF-8"); #endif // 将选定的编码方式设置为当前的本地编码、C字符串编码和翻译字符串编码 QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec); QTextCodec::setCodecForTr(codec); #else // 使用UTF-8编码 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // 将选定的编码方式设置为当前的本地编码 QTextCodec::setCodecForLocale(codec); #endif return a.exec(); }
这里仅对于.xml文件的写入和读取做了展示,.ini文件的操作完全一样。可自行运行体验。
至此,整个项目代码展示和运行结果展示完毕。建议学习之前首先对于xml文件和ini文件做一个提前了解。然后就是中文编码问题(这个问题困扰了我一段时间,还需进一步学习)也需要好好学一下。
有问题可以联系本人,私信会不定时看。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。