首页 前端知识 JSON,XML,INI配置文件的区别与使用

JSON,XML,INI配置文件的区别与使用

2025-02-24 13:02:11 前端知识 前端哥 73 14 我要收藏

1 配置管理

正常的应用程序在启动时通常需要从配置文件中恢复配置数据。这些配置文件的格式有很多种,如 INIXMLJSON 等。在本文中,我们将重点介绍 JSON 格式,它是一种轻量级的数据交换格式。

1.1 JSON 格式

JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成。它主要用于在服务器和 Web 应用之间传递数据,但也广泛应用于存储配置文件、数据库的数据交换等场景。

1.1.1 JSON 格式基本规则

  1. 数据由键值对组成:每个键(key)都是一个字符串,后面跟着一个冒号 : 和对应的值(value)。
  2. 键值对之间用逗号分隔
  3. 键必须是字符串,而值可以是:
    • 字符串(必须用双引号 "" 包裹)
    • 数字(整数或浮动)
    • 布尔值(truefalse
    • 数组(由方括号 [] 包裹)
    • 对象(由花括号 {} 包裹)
    • null
  4. 对象和数组可以嵌套:JSON 允许对象和数组互相嵌套,方便表示复杂的数据结构。

1.1.2 JSON 格式示例

以下是一个配置文件的 JSON 格式示例,该配置文件保存了一些系统设置,如串口波特率、杠杆臂参数、NTRIP 配置等。

{
    "com_baudrate": {
        "com1": "9600",
        "com2": "115200",
        "com3": "4800"
    },
    "lever_arm_gps": {
        "x": "0.1",
        "y": "0.2",
        "z": "0.3"
    },
    "lever_arm_lcp": {
        "x": "0.4",
        "y": "0.5",
        "z": "0.6"
    },
    "ntrip": {
        "ip": "192.168.1.1",
        "port": "2101",
        "username": "user",
        "password": "password",
        "mount_point": "mountpoint"
    },
    "output": {
        "GPFPD_BIN": true,
        "GTIMU_BIN": false,
        "TEST_BIN_1": true
    },
    "storage_path": "/path/to/storage",
    "decimal": "2"
}

1.1.3 python中JSON 解析和生成

在python中,可以使用 json 模块来解析和生成 JSON 格式的数据。

这里是存储json的代码,key-value形式存储到文件中,可以当做是C语言中的数组或者是结构体。

  import json
      def save_config_to_file(self):
      """保存配置到 JSON 文件"""
      config = {
          "com_baudrate": {
              "com1": self.com1_baudrate_combo.currentText(),
              "com2": self.com2_baudrate_combo.currentText(),
              "com3": self.com3_baudrate_combo.currentText()
          },
          "lever_arm_gps": {
              "x": self.gps_lever_arm_x.text(),
              "y": self.gps_lever_arm_y.text(),
              "z": self.gps_lever_arm_z.text()
          },
          "lever_arm_lcp": {
              "x": self.lcp_lever_arm_x.text(),
              "y": self.lcp_lever_arm_y.text(),
              "z": self.lcp_lever_arm_z.text()
          },
          "ntrip": {
              "ip": self.ntrip_ip.text(),
              "port": self.ntrip_port.text(),
              "username": self.ntrip_user.text(),
              "password": self.ntrip_password.text(),
              "mount_point": self.ntrip_mountpoint.text()
          },
          "output": {
              "GPFPD_BIN": self.gpfpd_checkbox.isChecked(),
              "GTIMU_BIN": self.gtimu_checkbox.isChecked(),
              "TEST_BIN_1": self.testbin1_checkbox.isChecked()
          },
          "storage_path": self.file_path_display.text(),  # 保存用户选择的存储路径
          "decimal":self.decimal_input.text()
      }

      try:
          print(f"Configuration file path: {CONFIG_FILE}")

          with open(CONFIG_FILE, "w") as file:
              json.dump(config, file, indent=4)

          if os.path.exists(CONFIG_FILE):
              print("Configuration file exists.")
          else:
              print("Configuration file not found.")
          with open(CONFIG_FILE, "r") as file:
              print(file.read())

      except Exception as e:
          QMessageBox.critical(self, "Error", f"Failed to save configuration: {e}")

这里是加载的代码,可以直接从文件中读取配置,并恢复到界面上。访问类似于C语言中的数组格式,config[“com_baudrate”][“com1”] 这样的形式来获取配置。

  def load_config_from_file(self):
      """从 JSON 文件加载配置"""
      if not os.path.exists(CONFIG_FILE):
          return  # 如果配置文件不存在,跳过加载

      try:
          with open(CONFIG_FILE, "r") as file:
              config = json.load(file)

          # 恢复串口波特率
          self.com1_baudrate_combo.setCurrentText(config["com_baudrate"]["com1"])
          self.com2_baudrate_combo.setCurrentText(config["com_baudrate"]["com2"])
          self.com3_baudrate_combo.setCurrentText(config["com_baudrate"]["com3"])

          # 恢复杠杆臂参数
          self.gps_lever_arm_x.setText(config["lever_arm_gps"]["x"])
          self.gps_lever_arm_y.setText(config["lever_arm_gps"]["y"])
          self.gps_lever_arm_z.setText(config["lever_arm_gps"]["z"])
          self.lcp_lever_arm_x.setText(config["lever_arm_lcp"]["x"])
          self.lcp_lever_arm_y.setText(config["lever_arm_lcp"]["y"])
          self.lcp_lever_arm_z.setText(config["lever_arm_lcp"]["z"])

          # 恢复 NTRIP 配置
          self.ntrip_ip.setText(config["ntrip"]["ip"])
          self.ntrip_port.setText(config["ntrip"]["port"])
          self.ntrip_user.setText(config["ntrip"]["username"])
          self.ntrip_password.setText(config["ntrip"]["password"])
          self.ntrip_mountpoint.setText(config["ntrip"]["mount_point"])

          # 恢复输出设置
          self.gpfpd_checkbox.setChecked(config["output"]["GPFPD_BIN"])
          self.gtimu_checkbox.setChecked(config["output"]["GTIMU_BIN"])
          self.testbin1_checkbox.setChecked(config["output"]["TEST_BIN_1"])

          # 恢复存储路径
          if "storage_path" in config:
              self.file_path_display.setText(config["storage_path"])

          if "decimal" in config:
              self.decimal_input.setText(config["decimal"])
          print("Configuration loaded successfully.")
      except Exception as e:
          QMessageBox.critical(self, "Error", f"Failed to load configuration: {e}")

1.1.4 c++中JSON 解析和生成

C++中也有直接的模块,本次示例为QT中对于JSON格式的示例,主要是使用QJsonDocument和QJsonObject来解析和生成JSON数据。
对于modbus寄存器与地址来说,使用json格式存储到文件中,方便读取和修改。

#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
void ConfigManager::saveModbusRegistersToJson(const QVector<QPair<int, QString>> &registers) {
    // 创建一个 JSON 数组,用来存放所有 Modbus 寄存器数据
    QJsonArray jsonArray;

    // 遍历传入的寄存器列表,将每个寄存器的数据转换为 JSON 对象,并添加到 JSON 数组中
    for (const auto &reg : registers) {
        QJsonObject jsonObj;

        // 将寄存器的地址(整数类型)和名称(字符串类型)添加到 JSON 对象中
        jsonObj["address"] = reg.first;  // 寄存器的地址
        jsonObj["name"] = reg.second;    // 寄存器的名称

        // 将这个 JSON 对象添加到 JSON 数组中
        jsonArray.append(jsonObj);
    }

    // 创建根 JSON 对象
    QJsonObject rootObj;
 
    rootObj["ModbusRegisters"] = jsonArray;

    // 创建 QJsonDocument 对象来保存 JSON 数据
    QJsonDocument jsonDoc(rootObj);

    QFile file("modbus_registers.json");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {

        file.write(jsonDoc.toJson());

        file.close();成功
    } else {

        qDebug() << "Failed to save Modbus registers to JSON file.";
    }
}

这里是加载的代码,和上面的代码类似于组包与解包的过程,将json数据转换为QVector<QPair<int, QString>>类型。

QVector<QPair<int, QString>> ConfigManager::loadModbusRegistersFromJson() {
    QVector<QPair<int, QString>> registers;
    QFile file("modbus_registers.json");

    if (!file.exists()) {
        qDebug() << "JSON file not found, returning empty register list.";
        return registers;
    }

    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QByteArray jsonData = file.readAll();
        file.close();
        // 创建 QJsonDocument 对象来解析 JSON 数据
        QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
        if (jsonDoc.isObject()) {
            // 获取根 JSON 对象
            QJsonObject rootObj = jsonDoc.object();
            // 获取 Modbus 寄存器数组
            if (rootObj.contains("ModbusRegisters") && rootObj["ModbusRegisters"].isArray()) {
                // 遍历 Modbus 寄存器数组,将每个 JSON 对象转换为 QPair<int, QString> 类型,并添加到列表中
                QJsonArray jsonArray = rootObj["ModbusRegisters"].toArray();
                for (const QJsonValue &value : jsonArray) {
                    if (value.isObject()) {
                        QJsonObject jsonObj = value.toObject();
                        int address = jsonObj["address"].toInt();
                        QString name = jsonObj["name"].toString();
                        registers.append(qMakePair(address, name));
                    }
                }
            }
        } else {
            qDebug() << "Invalid JSON format in file.";
        }
    } else {
        qDebug() << "Failed to open JSON file for reading.";
    }

    qDebug() << "Modbus registers loaded from JSON file:" << registers;
    return registers;
}

python与c++的json解析和生成的过程基本相同,只是在python中使用json模块,而在c++中则使用QJsonDocument和QJsonObject。相对来说,python的json模块更加简单易用,只需要直接配置好格式,dump和load即可,其余的操作内部会直接实现并不用关心。而c++则需要自己组包和解包,但也更加灵活。

1.1.5 C与JSON

C语言中,有轻量级的cJSON库,可以用来解析和生成JSON数据。还会用C的偏向于单片机,对于内存使用有限制,最好的做法只是解析JSON格式转换成结构体,然后再操作结构体。

1.2 INI 格式

INI (Initialization File) 是 Windows 系统中常用的配置文件格式,它是一种简单的文件格式,易于人阅读和编写,也易于机器解析和生成。它主要用于 Windows 系统的注册表,但也广泛应用于存储配置文件、数据库的数据交换等场景。

pip install some-package -i https://pypi.tuna.tsinghua.edu.cn/simple 

1.3 XML 格式

XML (Extensible Markup Language) 是一种标记语言,它是一种标准通用标记语言,由 W3C 组织推荐使用。它是一种结构化的标记语言,易于人阅读和编写,也易于机器解析和生成。它主要用于存储和交换各种数据,如电子邮件、网页、配置数据、元数据等。

在QT中,使用到XML的地方主要是Qt做语言翻译的.ts文件。

JSON相对来说适合做大量数据的转换配置记录
INI相对来说适合做一些简单的配置项记录
XML目前只在ts中使用到,其他地方并未使用

转载请注明出处或者链接地址:https://www.qianduange.cn//article/21130.html
标签
评论
发布的文章

C/C | 每日一练 (2)

2025-02-24 13:02:49

Linux性能监控工具汇总

2025-02-24 13:02:48

Python常见面试题的详解16

2025-02-24 13:02:48

QQ登录测试用例报告

2025-02-24 13:02:47

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!