1. QDataStream介绍

数据流是编码信息的二进制流,与主机的操作系统、CPU 或字节顺序完全无关。例如,Windows 系统下 PC 写入的数据流可由运行 Solaris 的 Sun SPARC 读取。

您还可以使用数据流读/写raw unencoded binary data 。如果需要 "解析 "输入流,请参阅QTextStream 。

QDataStream 类实现了 C++ 基本数据类型的序列化,如char,short,int,char * 等。更复杂数据的序列化是通过将数据分解成原始单元来实现的。

上面内容参考于:QDataStream Class | Qt Core | Qt 6.9.1

2. QSettings介绍

用户通常希望应用程序能跨会话记住其设置(窗口大小和位置、选项等)。在 Windows 系统中,这些信息通常存储在系统注册表中,而在 macOS 和 iOS 中则存储在属性列表文件中。在 Unix 系统上,由于缺乏标准,许多应用程序(包括 KDE 应用程序)都使用 INI 文本文件。

QSettings 是对这些技术的抽象,使您能以可移植的方式保存和恢复应用程序设置。它还支持custom storage formats 。

QSettings 的 API 基于QVariant ,允许您以最小的代价保存大多数基于值的类型,如QString 、QRect 和QImage 。

上面内容参考于:QSettings Class | Qt Core | Qt 6.9.1

3.demo

1. 需求:键值使用QDataStream转换成二进制数据存储到a.ini文件中;同时可以解析a.ini内容到output.ini中。

#include <QCoreApplication>
#include <QSettings>
#include <QFile>
#include <QDataStream>
#include <QDebug>
#include <QByteArray>// 序列化数据并存储到 a.ini(按 key=value 格式,但值是二进制)
void saveToSettings() {// 1. 准备要序列化的数据QString str = "the answer is";qint32 num = 42;// 2. 分别序列化 str 和 num,并存储到 a.ini 的对应键中QSettings settings("a.ini", QSettings::IniFormat);// 序列化 str 并存储到 text 键QByteArray strData;QDataStream strOut(&strData, QIODevice::WriteOnly);strOut << str;settings.setValue("text", strData);// 序列化 num 并存储到 number 键QByteArray numData;QDataStream numOut(&numData, QIODevice::WriteOnly);numOut << num;settings.setValue("number", numData);qDebug() << "Data serialized and saved to a.ini (Base64 encoded)";
}// 从 a.ini 读取并反序列化,然后写入 output.ini
void loadAndWriteToOutputIni() {// 1. 从 a.iniQSettings settings("a.ini", QSettings::IniFormat);// 读取 text 并反序列化QByteArray strData = (settings.value("text").toByteArray());QDataStream strIn(strData);QString str;strIn >> str;// 读取 number 并反序列化QByteArray numData = (settings.value("number").toByteArray());QDataStream numIn(numData);qint32 num;numIn >> num;// 2. 将解析后的数据写入 output.ini(标准键值对格式)QSettings outputSettings("output.ini", QSettings::IniFormat);outputSettings.setValue("text", str);outputSettings.setValue("number", num);qDebug() << "Deserialized data written to output.ini";qDebug() << "Output String:" << str;qDebug() << "Output Number:" << num;
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);saveToSettings();         // 序列化并存储到 a.iniloadAndWriteToOutputIni(); // 从 a.ini 读取并写入 output.inireturn a.exec();
}

运行结果如下:

(1)存入文件a.ini

(2)解析文件output.ini

2.需求:写一个解析a.ini内容所有节、键值对的代码到output.ini中。

#include <QCoreApplication>
#include <QSettings>
#include <QFile>
#include <QDataStream>
#include <QDebug>
#include <QByteArray>// 反序列化二进制数据(假设存储的是 QString 或 qint32)
QVariant deserializeBinaryData(const QByteArray &data) {QDataStream stream(data);QVariant result;// 尝试反序列化为 QStringQString str;stream >> str;if (!stream.status()) {return str;}// 尝试反序列化为 qint32stream.device()->seek(0); // 重置流位置qint32 num;stream >> num;  //!!!这里数字转换正确了,但是stream转换错误,可能跟字节序有关,处理方法:设置字节序或者数字直接以原始数字存储,非二进制存储。if (stream.status() == QDataStream::Ok) {return num;}// 如果都不是,返回原始 QByteArrayreturn data;
}// 遍历 a.ini 的所有节和键值对,反序列化二进制数据并写入 output.ini
void processIniFile() {// 检查 a.ini 是否存在if (!QFile::exists("a.ini")) {qCritical() << "Error: a.ini does not exist!";return;}QSettings inputSettings("a.ini", QSettings::IniFormat);QSettings outputSettings("output.ini", QSettings::IniFormat);QStringList allKeys = inputSettings.allKeys(); // 例如: ("General/number", "General/text")foreach (const QString &fullKey, allKeys) {// 提取节名和键名int lastSlash = fullKey.lastIndexOf('/');QString section = fullKey.left(lastSlash);QString key = fullKey.mid(lastSlash + 1);// 读取原始数据并反序列化QByteArray rawData = inputSettings.value(fullKey).toByteArray();QVariant value = deserializeBinaryData(rawData);// 写入 output.inioutputSettings.beginGroup(section);outputSettings.setValue(key, value);outputSettings.endGroup();}qDebug() << "Processed a.ini and wrote to output.ini";
}int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);processIniFile(); // 遍历 a.ini 并写入 output.inireturn a.exec();
}

运行结果如下:

上面的内容转出内容有下面问题:

(1)键值对结构错误。

        由于之前使用下面代码,inputSettings.childGroups返回的内容是空,所以使用的上面上面方法遍历键值。

    // 1. 遍历所有节(Sections)QStringList sections = inputSettings.childGroups();foreach (const QString &section, sections) {inputSettings.beginGroup(section);outputSettings.beginGroup(section);// 2. 遍历当前节的所有键QStringList keys = inputSettings.childKeys();foreach (const QString &key, keys) {QByteArray rawData = inputSettings.value(key).toByteArray();QVariant value = deserializeBinaryData(rawData);// 3. 写入 output.ini(保持相同的键值对结构)outputSettings.setValue(key, value);}inputSettings.endGroup();outputSettings.endGroup();}

查阅的资料得到的一种解释是:QSettings 的 childGroups() 行为:
childGroups() 返回的是 当前组(Group)下的子组,而不是当前组本身。
如果你没有调用 beginGroup() 进入某个组,childGroups() 返回的是 顶层组(即 [] 空组的子组)。
如果 a.ini 只有 [General] 这一层,而没有嵌套的子组(如 [General/SubSection]),那么 childGroups() 可能会返回空列表。

(2)数字没有正确解析。

实际测试中stream >> num;  这里数字转换正确了,但是stream转换错误,可能跟字节序有关,处理方法:设置字节序或者数字直接以原始数字存储,而非二进制存储。

查阅的资料得到的一种解释是:从理论上看,二进制流可以设计为完全独立于硬件(如 UTF-8 编码的文本),但实际场景中(如 QDataStream 或网络协议),二进制流的解释往往依赖隐式或显式的字节序约定。

CMakeLists.txt文件如下:

cmake_minimum_required(VERSION 3.5)project(testQDataB LANGUAGES CXX)set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)find_package(Qt5Core)add_executable(testQDataBmain.cpp
)
target_link_libraries(testQDataB Qt5::Core)

附加

读写ini也可参考:总结:Qt读写ini配置文件(QSettings)_qt ini-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95513.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95513.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/95513.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Typer 命令行工具使用示例

Typer 命令行工具使用示例 示例1&#xff1a;简单问候程序 代码 import typerapp typer.Typer()app.command() def greet(name: str):"""简单的问候命令"""typer.echo(f"Hello {name}!")if __name__ "__main__":app()使用…

关于CAN总线bus off 理论标准 vs 工程实践

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

CAN堆栈

PDU映射到HOH将硬件对象句柄HOH抽象成为硬件抽象层CanIf将pdu映射到硬件对象句柄上一个HOH代表一个Can控制器的一个消息缓冲区发送缓存区当所有Can硬件资源被占用时&#xff0c;LPDU存储在缓冲区中。发送取消为了解决优先级反转的问题&#xff0c;高优先级L-PDU会请求取消低优先…

sub3G和sub6G的区别和联系

Sub-3G 和 Sub-6G 的区别与联系Sub-3G 和 Sub-6G 是无线通信中频段的不同分类&#xff0c;尤其在4G LTE和5G网络中&#xff0c;定义了无线信号传输的不同频率范围。具体来说&#xff0c;Sub-3G 通常指的是低于3 GHz的频段&#xff0c;而 Sub-6G 是指低于6 GHz的频段。这些频段的…

【数据可视化-106】华为2025上半年财报分析:用Python和Pyecharts打造炫酷可视化大屏

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…

Scikit-learn Python机器学习 - 特征预处理 - 归一化 (Normalization):MinMaxScaler

锋哥原创的Scikit-learn Python机器学习视频教程&#xff1a; 2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程主要讲解基于Scikit-learn的Python机器学习知识&#xff0c;包括机器学习概述&#xff0c;特征工程(数据…

LINUX_Ubunto学习《2》_shell指令学习、gitee

0、前言&#xff1a; 0.1、为什么学习shell脚本 学习Shell&#xff08;Shell脚本编程&#xff09;是提升系统管理和开发效率的重要技能&#xff0c;尤其在Linux/Unix环境中作用显著。Shell是用户与操作系统内核的接口&#xff0c;学习Shell有助于掌握系统工作原理。shell的核心…

系统安装与迁移工具,一键下载系统并制作U盘启动盘

大家好&#xff0c;今天想跟大家分享一款非常实用的软件——Hasleo WinToUSB 下载地址获取 点击获取&#xff1a;WinToUSB启动盘 打开后的界面&#xff1b; image Windows To Go USB 可以安装或克隆 Windows 到 USB 设备&#xff0c;作为便携式 Windows 使用 可以选择直接用…

日语学习-日语知识点小记-构建基础-JLPT-N3阶段(26):文法+单词第8回3 复习 +考え方6

日语学习-日语知识点小记-构建基础-JLPT-N3阶段&#xff08;&#xff12;6&#xff09;&#xff1a;文法单词第8回3 复习1、前言&#xff08;1&#xff09;情况说明&#xff08;2&#xff09;工程师的信仰2、知识点1ー V辞書形 &#xff0b; ことができます。2ーこの橋、&am…

AM J BOT | 黄芪稳健骨架树构建

Astragalus&#xff08;黄芪属&#xff0c;豆科&#xff0c;含约 3,400 种&#xff09;是最大的被子植物属之一&#xff0c;其多样化在北半球多个地区的植被形成与生物多样性格局中扮演了重要角色。然而&#xff0c;由于属内物种数量庞大、形态复杂且演化历史可能受到网状进化的…

if __name__=‘__main__‘的用处

在 Python 中&#xff0c;if __name__ __main__:是一个常见的代码模式&#xff0c;用于控制模块的执行行为。它的核心作用是区分模块是被直接运行还是被导入到其他文件中。作用详解&#xff1a;​当文件被直接运行时​__name__会被自动设置为 __main__&#xff0c;此时 if块内…

MySQL慢查询优化策略

一、问题定位 1、慢查询日志 -- 查看当前设置 SHOW VARIABLES LIKE slow_query%; ​ -- 开启慢查询日志&#xff08;my.cnf永久配置&#xff09; [mysqld] slow_query_log 1 slow_query_log_file /var/log/mysql/slow.log long_query_time 1 -- 超过1秒的查询 log_querie…

如何使用 ASP.NET Core 创建基于角色的 Web API

在使用 ASP.NET Core 构建基于角色的 Web API 时&#xff0c;代码优先方法是一种强大而高效的方法。使用它&#xff0c;我们可以在代码中定义数据模型和关系&#xff0c;然后自动生成相应的数据库模式。这会带来什么&#xff1f;当然是更快的开发周期和更大的灵活性。为什么&am…

无字母数字命令执行

写在前面 说白了数字还是好构造的&#xff0c;bash的算数拓展&#xff01; base64命令 这玩意说白了有点鸡肋&#xff0c;因为你得知道flag的文件名和位置&#xff01; base64 flag.php这个会将flag.php里面的内容给base64编码输出来。那么如何用无字母数字构造呢&#xff1f; …

AAB包转apks转apk

1. 下载bundletool-all-1.17.2.jar&#xff08;不一定非得1.17.2&#xff0c;可以其他版本&#xff09; https://github.com/google/bundletool/releases/tag/1.17.2 2. 在aab、keystore、bundletool-all-1.17.2.jar的目录下&#xff0c;运行指令 java -jar bundletool-all-1…

从零开始:用uv构建并发布一个Python CLI应用,集成CI/CD自动化发布与Docker容器化部署

使用uv构建并发布一个完整的Python CLI应用 概述 初始化项目 编写应用代码 定义项目 (`pyproject.toml`) 使用`uv`安装依赖 本地运行和测试 依赖锁定 构建 发布 生产环境实践之CI/CD 创建工作流配置文件 配置GitHub Secrets 创建和推送tag 验证发布 生产环境实践之Docker 创建D…

如何在Qt中使用周立功USB转CAN卡

如何在 Qt 中使用周立功 USB 转 CAN 卡 文章目录如何在 Qt 中使用周立功 USB 转 CAN 卡一、简介二、准备工作三、使用四、运行效果五、写在最后​一、简介 最近在工程中用到了周立功的 USB 转 CAN 卡&#xff0c;需求是要通过上位机进行通信&#xff0c;因此有了这篇文章。 有…

JavaScript 源码剖析:从字节码到执行的奇妙旅程

JavaScript&#xff0c;这门风靡全球的脚本语言&#xff0c;以其灵活性和跨平台性征服了无数开发者。我们每天都在使用它&#xff0c;但它在后台是如何工作的&#xff1f;一段看似简单的JS代码&#xff0c;在执行之前究竟经历了哪些“变形记”&#xff1f;今天&#xff0c;让我…

FPGA—硬件电路一旦上电配置完成,各个功能模块会并行地持续工作

1.示例代码参考这段代码是用 Verilog 编写的一个 LED 闪烁控制模块&#xff0c;主要实现了 LED 按一定时间间隔循环移位闪烁的功能。下面详细解释其架构组成&#xff1a;模块定义与端口声明模块名为 led_flash&#xff0c;包含三个端口&#xff1a;sys_clk&#xff1a;输入端口…

从零到上线:Docker、Docker Compose 与 Runtime 安装部署全指南(含实战示例与应用场景)

文章目录一、Docker 安装1. Ubuntu / Debian&#xff08;官方仓库&#xff09;2. RHEL / CentOS / Rocky / AlmaLinux3. 验证4. macOS / Windows&#xff08;Docker Desktop&#xff09;二、Docker Compose&#xff08;V2&#xff09;安装与基本用法1) 验证2) 最小示例&#xf…