Qt服务应用操作

0.前置知识

1. ini文件

INI(初始化文件)是一种配置文件格式,广泛用于存储配置数据。它通常用于操作系统、应用程序和软件库的配置。INI 文件以文本形式存储数据,并且具有以下特点:

  1. 简单性:INI 文件的结构简单,易于阅读和编辑,通常由注释、节(sections)和键值对(key-value pairs)组成。
  2. 节(Sections):INI 文件由多个节组成,每个节都有一个方括号包围的标题,例如 [General][Settings]。节用于逻辑上分组相关的配置项。
  3. 键值对(Key-Value Pairs):在每个节中,配置数据以键值对的形式存储,键和值之间用等号(=)分隔。例如:
    Width=800
    Height=600
    
  4. 注释:INI 文件支持注释,以分号(;)或井号(#)开头的行被视为注释,不会被程序解析。
  5. 大小写敏感性:在某些系统中,INI 文件的键名是大小写敏感的,这意味着 Widthwidth 被视为两个不同的键。
  6. 多平台支持:INI 文件格式在不同的操作系统上都得到广泛支持,包括 Windows、Linux 和 macOS。
  7. 易于使用:由于其简单的格式,INI 文件可以很容易地被文本编辑器或专门的配置管理工具处理。
  8. 可扩展性:尽管INI文件的基本结构相对固定,但开发者可以根据需要添加自定义的节和键值对。
  9. 应用场景:INI 文件常用于存储用户偏好设置、程序参数、系统配置等,它们可以在程序启动时被读取,以初始化程序的状态。
  10. 示例:一个典型的 INI 文件可能如下所示:
    ; 这是注释
    [General]
    Name=My Application
    Version=1.0
    
    [Settings]
    Width=1024
    Height=768
    Language=English
    

INI 文件是一种非常基本的配置文件格式,尽管它在现代应用程序中可能不如 JSON 或 XML 那样常见,但它仍然因其简单性和易于使用而在某些场景下被广泛使用。

2.JSON文件

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,但独立于语言,被广泛用于数据交换和配置文件。以下是JSON的一些关键特点:

  1. 文本格式:JSON是一种纯文本格式,可以由任何文本编辑器生成或读取。
  2. 数据类型:JSON支持以下数据类型:
    • 字符串(String)
    • 数字(Number)
    • 对象(Object),无序的键值对集合
    • 数组(Array),有序的值集合
    • 布尔值(Boolean)
    • 空值(Null)
  3. 键值对:JSON对象由键值对组成,键是字符串,值可以是字符串、数字、对象、数组、布尔值或空值。
  4. 数组:JSON数组是有序的值集合,可以包含不同类型的值。
  5. 可扩展性:JSON结构可以非常灵活,支持嵌套对象和数组。
  6. 自描述性:JSON数据格式本身不包含数据类型信息,但通过结构可以推断数据类型。
  7. 语言无关性:虽然JSON起源于JavaScript,但它与编程语言无关,可以被多种编程语言解析和生成。
  8. 易于解析:许多编程语言都提供了解析JSON的工具和库,使得处理JSON数据变得简单。
  9. 广泛使用:JSON在Web开发中非常流行,常用于客户端和服务器之间的数据交换,也被用于配置文件、日志文件等。
  10. 示例
    {
      "name": "John Doe",
      "age": 30,
      "is_student": false,
      "grades": [88, 92, 77],
      "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "zip": "12345"
      }
    }
    
  11. 安全性:由于JSON格式的简单性,它不容易受到注入攻击,但处理JSON数据时仍需注意安全性,避免执行不安全的解析操作。
  12. 应用场景:JSON常用于以下场景:
    • Web API响应和请求
    • 配置文件
    • 数据存储和传输
    • 日志记录
    • 应用程序的本地存储
      由于其简单性和灵活性,JSON已经成为数据交换和配置管理中的首选格式之一。

不同类间关系

QJsonDocumentQJsonObjectQJsonValue 是 Qt 框架中处理 JSON 数据的三个核心类,它们之间的关系如下:

  1. QJsonDocument
    • QJsonDocument 是一个类,用于表示 JSON 文档。它可以包含一个 JSON 对象(QJsonObject)或一个 JSON 数组(QJsonArray)。
    • 它提供了从字符串或数据创建 JSON 文档的功能,以及将 JSON 文档转换为字符串或数据的功能。
    • QJsonDocument 可以被视为 JSON 数据的容器。
  2. QJsonObject
    • QJsonObject 是一个类,表示 JSON 对象,即一组键值对,其中键是字符串,值可以是字符串、数字、布尔值、null、另一个 JSON 对象或 JSON 数组。
    • 它提供了添加、查询和删除键值对的方法。
    • QJsonObjectQJsonDocument 可以包含的数据类型之一。
  3. QJsonValue
    • QJsonValue 是一个类,表示 JSON 值,它可以是以下类型之一:字符串、数字、布尔值、null、QJsonObjectQJsonArray
    • 它是一个变体类型,可以存储 JSON 数据的任何基本类型,以及 JSON 对象和数组。
    • QJsonValue 用于访问和操作 QJsonObject 中的值。
      这三个类之间的关系可以这样理解:QJsonDocument 是整个 JSON 数据的顶层容器,它可以包含一个 QJsonObjectQJsonArrayQJsonObject 是实际存储键值对的地方,而 QJsonValueQJsonObject 中键对应的值的类型。
      例如,如果你有一个 JSON 对象如下:
{
  "name": "John Doe",
  "age": 30,
  "is_student": false,
  "grades": [88, 92, 77]
}

在这个例子中:

  • QJsonDocument 将包含整个 JSON 对象。
  • QJsonObject 将包含键 "name", "age", "is_student", 和 "grades",以及它们对应的值。
  • QJsonValue 将分别表示每个键对应的值,例如 "John Doe"(字符串)、30(数字)、false(布尔值)和 [88, 92, 77](数组)。
    使用 Qt 的 JSON API,你可以轻松地解析 JSON 字符串,创建和修改 JSON 对象,以及序列化 JSON 对象回字符串。

3.XML文件

XML(可扩展标记语言,eXtensible Markup Language)是一种标记语言,主要用于存储和传输数据。它被设计为简单、易于理解和使用,同时具有自我描述性,这意味着数据的结构在数据本身中定义。以下是XML的一些关键特点:

  1. 自我描述性:XML文档中的元素和属性定义了数据的结构和含义,无需外部的DTD(文档类型定义)或XML Schema。
  2. 可扩展性:用户可以定义自己的元素和属性,使其适应不同的应用需求。
  3. 平台无关性:XML是一种纯文本格式,可以在任何操作系统和平台上使用。
  4. 数据和视图分离:XML专注于数据的存储和传输,而显示和处理数据则由其他技术(如CSS、XSLT等)处理。
  5. 支持命名空间:XML支持命名空间,允许不同来源的元素和属性在同一文档中共存而不发生冲突。
  6. 支持属性:XML元素可以包含属性,属性提供了关于元素的额外信息。
  7. 支持注释:XML支持注释,注释在文档中被忽略,但可以用于提供额外的信息或解释。
  8. 支持嵌套:XML元素可以嵌套在其他元素中,形成层次结构。
  9. 数据类型:XML Schema定义了数据类型,可以对元素和属性的值进行类型约束。
  10. 广泛使用:XML在许多领域中得到应用,如配置文件、数据交换、文档管理等。
  11. 示例
    <?xml version="1.0" encoding="UTF-8"?>
    <bookstore>
      <book>
        <title lang="en">Harry Potter</title>
        <author>J.K. Rowling</author>
        <year>1997</year>
        <price>29.99</price>
      </book>
      <book>
        <title lang="en">The Hobbit</title>
        <author>J.R.R. Tolkien</author>
        <year>1937</year>
        <price>19.99</price>
      </book>
    </bookstore>
    
  12. 解析和生成:许多编程语言提供了解析和生成XML的库,使得处理XML数据变得简单。
  13. 安全性:XML本身是安全的,但需要小心处理,避免XML注入攻击。
  14. 相关技术
    • XSLT(可扩展样式表语言转换):用于将XML文档转换为其他格式,如HTML、文本或另一个XML文档。
    • XPath:用于在XML文档中进行选择和导航。
    • XQuery:用于查询XML数据。
      XML是一种非常灵活和强大的数据交换格式,尽管在某些场景下可能被更轻量级的格式(如JSON)所取代,但它在许多领域中仍然非常重要和有用。

不同类之间的关系

在Qt框架中,处理XML文档涉及几个关键类,这些类共同构成了Qt的XML DOM(文档对象模型)API。以下是QDomDocumentQDomProcessingInstructionQDomElementQDomText这几个类的关系及其作用:

  1. QDomDocument

    • QDomDocument 类代表整个XML文档。它是所有其他DOM对象的容器。
    • 你可以使用 QDomDocument 来创建新的XML文档或加载现有的XML文档。
    • QDomDocument 提供了访问和修改文档中元素的方法,如 createElement()createTextNode()createElementNS() 等。
  2. QDomElement

    • QDomElement 类代表XML文档中的一个元素。元素是XML文档的基本构建块,可以包含文本、属性和其他元素。
    • 你可以使用 QDomElement 来访问元素的标签名、属性、子元素等。
    • QDomElement 也可以用来创建新的元素或修改现有元素。
  3. QDomText

    • QDomText 类代表XML元素中的文本节点。它用于存储元素的文本内容。
    • 每个 QDomText 对象都是 QDomNode 的子类,可以被添加到 QDomDocumentQDomElement 中。
  4. QDomProcessingInstruction

    • QDomProcessingInstruction 类代表XML文档中的处理指令(Processing Instruction)。处理指令通常用于提供关于文档的额外信息,例如指定样式表或转换指令。
    • 处理指令有一个目标(target)和一个数据(data),分别用于指定处理指令的类型和提供相关的数据。

关系和层次结构

  • QDomDocument 是最顶层的容器,包含整个XML文档。
  • QDomElement 是文档中的元素,可以包含 QDomText 节点和其他 QDomElement 节点(即子元素)。
  • QDomText 是元素的子节点,存储文本内容。
  • QDomProcessingInstruction 是文档的一部分,通常位于文档的顶部,提供关于文档的处理指令。

示例

假设有一个简单的XML文档:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<bookstore>
  <book>
    <title>Harry Potter</title>
    <author>J.K. Rowling</author>
    <year>1997</year>
  </book>
</bookstore>

在这个文档中:

  • QDomDocument 包含整个文档。
  • <bookstore> 是一个 QDomElement,它是文档的根元素。
  • <book>QDomElement 的子元素。
  • <title><author><year> 都是 QDomElement,包含书籍的标题、作者和出版年份。
  • Harry PotterJ.K. Rowling1997QDomText 节点,分别存储在相应的 QDomElement 中。
  • <?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="style.xsl"?>QDomProcessingInstruction,提供文档的版本信息和样式表链接。

通过这些类,Qt的XML DOM API提供了一种强大的方式来解析、创建和操作XML文档。

4. 不同的编码方法

在Qt中,处理字符串编码是一个常见的任务,尤其是当你需要在应用程序中处理不同语言或与不同系统交互时。Qt提供了几种方法来转换和处理字符串编码。以下是一些主要的编码转换方法及其用途:

  1. QString::toUtf8()
    • QString 对象转换为UTF-8编码的 QByteArray
    • UTF-8是最常用的Unicode编码方式,广泛用于网络传输和跨平台兼容性。
    • 用法示例:
      QByteArray utf8Data = myQString.toUtf8();
      
  2. QString::toLocal8Bit()
    • QString 对象转换为本地8位编码的 QByteArray
    • 本地编码通常是系统的默认编码(如Windows上的CP1252或Linux上的ISO-8859-1)。
    • 适用于将字符串发送到系统API或使用本地编码的文件。
    • 用法示例:
      QByteArray localData = myQString.toLocal8Bit();
      
  3. QString::fromLatin1()
    • QString 对象转换为Latin-1(ISO-8859-1)编码的 QByteArray
    • 主要用于西欧语言,不包含扩展字符。
    • 用法示例:
      QByteArray latin1Data = myQString.fromLatin1();
      
  4. QString::fromUtf8()
    • 将UTF-8编码的 QByteArray 或 C 风格字符串转换为 QString
    • 用于从外部源(如文件或网络)读取UTF-8编码的数据并转换为Qt内部的Unicode字符串。
    • 用法示例:
      QString unicodeString = QString::fromUtf8(someUtf8Data);
      
  5. QString::fromLocal8Bit()
    • 将本地8位编码的 QByteArray 转换为 QString
    • 用于从系统API或本地编码文件读取字符串,并转换为Unicode字符串。
    • 用法示例:
      QString unicodeString = QString::fromLocal8Bit(someLocalData);
      
  6. QTextCodec
    • QTextCodec 类提供了编码和解码的功能,支持各种编码。
    • 可以用于自定义编码的转换,或者作为更通用的解决方案。
    • 用法示例:
      QTextCodec *codec = QTextCodec::codecForName("GB18030");
      QByteArray encodedData = codec->fromUnicode(myQString);
      

为什么使用这些转换方法?

  • 跨平台兼容性:不同的操作系统可能有不同的默认编码,使用这些方法可以确保应用程序在不同平台上都能正确处理字符串。
  • 网络传输:网络通常使用UTF-8编码,因此将字符串转换为UTF-8格式是必要的。
  • 系统API:许多系统API要求使用特定的编码格式,例如Windows的API可能要求使用本地编码。
  • 国际化和本地化:应用程序可能会支持多种语言,正确处理不同语言的编码是提供良好用户体验的关键。
    理解并正确使用这些编码转换方法对于开发能够在全球范围内运行的应用程序至关重要。

1.INI文件读写

void WriteIniFiles()
{
    // 直接使用QSettings类读写INI文件
    QSettings *configWritenIniFiles = new QSettings("MySQLFiles.ini", QSettings::IniFormat);

    // 向ini文件中写入数据信息
    configWritenIniFiles->setValue("/database/ip", "192.168.12.189");
    configWritenIniFiles->setValue("/database/port", "6666");
    configWritenIniFiles->setValue("/database/user", "root");
    configWritenIniFiles->setValue("/database/password", "123456");

    configWritenIniFiles->setValue("/notice/version", "6.12");
    configWritenIniFiles->setValue("/notice/time", "17点22分");


    // 写入后删除指针
    delete configWritenIniFiles;
}
void ReadIniFiles()
{
    QSettings *configWritenIniFiles = new QSettings("MySQLFiles.ini", QSettings::IniFormat);

    QString strip = configWritenIniFiles->value("/database/ip").toString();

    qDebug() << strip.toUtf8().data();

    delete configWritenIniFiles;
}

2.Json文件读写

点击查看代码
void write()
{
    // 1、创建Json对象
    QJsonObject mySQLinfo;

    mySQLinfo.insert("ip", "192.168.1.1");
    mySQLinfo.insert("port", 6666);
    mySQLinfo.insert("user", "1");
    mySQLinfo.insert("password", "123");

    QJsonObject jsoninfo;
    jsoninfo.insert("code", 1);
    jsoninfo.insert("dbmsg", "MySQL数据库配置参数");
    jsoninfo.insert("data", mySQLinfo);

    // 2、创建Json文档
    QJsonDocument jsondoc;
    jsondoc.setObject(jsoninfo);

    // 3、创建文件
    QFile qfiles("./databaseJsonfiles.json");
    if(qfiles.open(QIODevice::WriteOnly))
    {
        qfiles.write(jsondoc.toJson());
        qfiles.close();
        qDebug() << "Json数据文件写入成功";
    }

    QMessageBox::information(this, "提示", "Json数据文件写入成功");
}


void read()
{
    QString strJson;

    // QFile 读取出来为QString格式
    QFile qfiles("./databaseJsonfiles.json");
    if( qfiles.open(QIODevice::ReadOnly))
    {
        strJson = qfiles.readAll();
        qfiles.close();
    }

    // 将QString格式转换为Json格式
    QJsonParseError jsonError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(strJson.toUtf8(), &jsonError);

    QString strTemp;
    if(!jsonDoc.isEmpty() && (jsonError.error == QJsonParseError::NoError))
    {
        // 只要Jsondoc不为空,和Jsonerror没有错误
        // 将他转换Json对象

        QJsonObject json = jsonDoc.object();
        QJsonValue code = json.value("code");
        QJsonValue data = json.value("data");

        // 检查数据
        if(code.isUndefined() || code.toDouble()!=1 || data.isUndefined() || !data.isObject())
        {
            QMessageBox::critical(this, "错误", "转换JSon数据错误,请重新检查");
            exit(100);
        }

        // 如果没有错误
        QJsonObject databaseinfo = data.toObject();

        QJsonValue dbip = databaseinfo.value("ip");
        QJsonValue dbport = databaseinfo.value("port");
        QJsonValue dbuser = databaseinfo.value("user");
        QJsonValue dbpassword = databaseinfo.value("password");

        // 检查接口是否正确

        if(dbip.isUndefined()
            || dbport.isUndefined()
            || dbuser.isUndefined()
            || dbpassword.isUndefined())
        {
            qDebug() << "接口错误";
            QMessageBox::critical(this, "错误", "接口错误");
            exit(100);
        }

        QString strip = dbip.toString();
        int port = dbport.toInt();
        QString struser = dbuser.toString();
        QString strPassword = dbpassword.toString();

        // 判断是否为空
        if(strip.isEmpty() || struser.isEmpty() ||strPassword.isEmpty())
        {
            qDebug() << "不能为空";
            QMessageBox::critical(this, "错误", "不能为空");
            exit(100);
        }

        QMessageBox::information(this, "提示",
                                 "QJson格式Json数据文件读取成功\n"
                                 "dbIP:" + strip + "\n"
                                 "dbPort:" + QString::number(port) + "\n"
                                 "dbUser:" + struser + "\n"
                                 "dbPassword:" + strPassword);
    }

    QMessageBox::information(this, "提示", "QString格式Json数据文件读取成功\n"+strJson);
}


3.XML文件读写

  1. GB2312 和 UTF-8 编码存在问题,未解决!!!
  2. 存在中文时可以写入,但是无法读出
点击查看代码
void MainWindow::on_pushButton_write_clicked()
{
    if (!openxmlfiles())
    {
        QMessageBox::critical(this, "警告", "打开文件失败");
        return;
    }

    QDomDocument domdoct; // 顶层容器,包含整个XML文档
    QDomProcessingInstruction version;
    version = domdoct.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
    domdoct.appendChild(version);

    QDomElement domrootelement = domdoct.createElement("factory"); // 创建顶层节点
    domdoct.appendChild(domrootelement);

    QDomElement itemrootelement = domdoct.createElement("worker"); // 创建父节点
    {
        QDomElement node1 = domdoct.createElement("ID");
        QDomText domtext1 = domdoct.createTextNode("ID");
        domtext1.setData(ui->lineEdit_id->text());
        node1.appendChild(domtext1);
        itemrootelement.appendChild(node1);

        QDomElement node2 = domdoct.createElement("Name");
        QDomText domtext2 = domdoct.createTextNode("Name");
        domtext2.setData(ui->lineEdit_name->text());
        node2.appendChild(domtext2);
        itemrootelement.appendChild(node2);

        QDomElement node3 = domdoct.createElement("Sex");
        QDomText domtext3 = domdoct.createTextNode("Sex");
        domtext3.setData(ui->lineEdit_sex->text());
        node3.appendChild(domtext3);
        itemrootelement.appendChild(node3);

        QDomElement node4 = domdoct.createElement("Edu");
        QDomText domtext4 = domdoct.createTextNode("Edu");
        domtext4.setData(ui->lineEdit_edu->text());
        node4.appendChild(domtext4);
        itemrootelement.appendChild(node4);

        QDomElement node5 = domdoct.createElement("Dep");
        QDomText domtext5 = domdoct.createTextNode("Dep");
        domtext5.setData(ui->lineEdit_dep->text());
        node5.appendChild(domtext5);
        itemrootelement.appendChild(node5);

        QDomElement node6 = domdoct.createElement("Slary");
        QDomText domtext6 = domdoct.createTextNode("Slary");
        domtext6.setData(ui->lineEdit_slary->text());
        node6.appendChild(domtext6);
        itemrootelement.appendChild(node6);
    }
    domrootelement.appendChild(itemrootelement);

    m_qfiles.write(domdoct.toString().toLocal8Bit().data());
    m_qfiles.close();

    QMessageBox::information(this, "提示", "写入文件成功");


}

void MainWindow::on_pushButton_read_clicked()
{
    if (!openxmlfiles())
    {
        QMessageBox::critical(this, "警告", "打开文件错误");
        return;
    }

    // QByteArray data = m_qfiles.readAll();

    QDomDocument domdoct;

    if (!domdoct.setContent(&m_qfiles))
    {
        m_qfiles.close();
        QMessageBox::critical(this, "警告", "setContent错误");
        return;
    }

    QDomElement root = domdoct.documentElement(); // 读取根节点, 类似于链表,需要从根节点开始读取

    QDomNode node = root.firstChild(); // 第一个子节点,也是一个包含许多节点的父节点

    while(!node.isNull())
    {
        QDomNodeList sonlist = node.childNodes(); // 第一个子节点中的所有节点信息
        QString rootname = node.toElement().tagName(); // 读取父节点的标签名

        if (rootname.compare("worker") == 0)
        {
            // 将子节点集合信息读取出来
            readrootxml(sonlist);
        }
        node = node.nextSibling(); //读取下一个父节点
    }



}

bool MainWindow::openxmlfiles()
{
    m_qfiles.setFileName(strCurrentFilePath + strCurrentFileName);// 如果没有,则创建文件
    return m_qfiles.open(QIODevice::ReadWrite | QFile::Text);
}

void MainWindow::readrootxml(QDomNodeList sonnodelist)
{
    for (int sonnode = 0; sonnode < sonnodelist.size(); sonnode++)
    {
        // 获取子节点
        QDomElement sonelement = sonnodelist.at(sonnode).toElement();

        if(sonelement.toElement().tagName().compare("ID") == 0) // 取出子节点进行比较
        {
            ui->lineEdit_id2->setText(sonelement.text());
        }
        else if(sonelement.toElement().tagName().compare("Name") == 0)
        {
            ui->lineEdit_name2->setText(sonelement.text());
        }else if(sonelement.toElement().tagName().compare("Sex") == 0)
        {
            ui->lineEdit_sex2->setText(sonelement.text());
        }else if(sonelement.toElement().tagName().compare("Edu") == 0)
        {
            ui->lineEdit_edu2->setText(sonelement.text());
        }else if(sonelement.toElement().tagName().compare("Dep") == 0)
        {
            ui->lineEdit_dep2->setText(sonelement.text());
        }else if(sonelement.toElement().tagName().compare("Slary") == 0)
        {
            ui->lineEdit_slary2->setText(sonelement.text());
        }
    }
}

posted @ 2024-07-19 10:03  xjx111  阅读(29)  评论(0编辑  收藏  举报