Qt中QSettings的鍵值使用QDataStream進行存儲

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…