簡述
一般情況下,我們在開發軟件過程中,都會緩存一些信息到本地,可以使用輕量級數據庫sqlite,也可以操作注冊表、讀寫配置文件。
關於QSettings的使用前面已經介紹過了,比較詳細,見“更多參考”,下面介紹下QSettings常用功能-讀寫注冊表、配置文件。
優點
無需指定注冊表路徑
一般情況下,我們需要定義一個宏,或者常量字符串來指定保存的注冊表位置。
#define HKEY_CURRENT_USER_QT "HKEY_CURRENT_USER\\SoftWare\\Digia\\Qt"
const QString HKEY_CURRENT_USER_QT = "HKEY_CURRENT_USER\\SoftWare\\Digia\\Qt";
無需指定配置文件路徑
一般情況下,我們需要定義一個宏,或者常量字符串來指定保存的配置文件位置及名稱。
#define INI_QT "C:\Users\WangLiang\AppData\Roaming\Digia"
const QString INI_QT = "C:\Users\WangLiang\AppData\Roaming\Digia";
采用下面方式,我們不需要做太多工作,Qt已經很好的替你實現了!
讀寫注冊表
一般存儲
下面我們以Qt為例,眾所周知現在Qt已經屬於Digia,也就是說:組織名為Digia,產品名為Qt。
在main()函數中,首先設置組織名、產品名。
QCoreApplication::setOrganizationName(QString("Digia"));
QCoreApplication::setApplicationName(QString("Qt"));
然后使用QSettings對注冊表進行操作:
QSettings settings(QSettings::NativeFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", 5);
這時,我們打開注冊表regedit,數據就生成了。
一般讀取
存儲完數據之后,默認的程序啟動時需要加載對應的數據。
QString strName = settings.value("Name").toString();
int nVersion = settings.value("Version").toInt();
//Name:Qt Creator Version:5
這時,我們可以通過查看應用程序輸出窗口得到輸出結果。
分目錄存儲
如果我們需要在同一路徑下建立多個子目錄該怎么辦,下面介紹兩種方式。
替換applicationName
如上,我們可以看出,organizationName對應的注冊表路徑為HKEY_CURRENT_USER\\SoftWare\\Digia
,applicationName對應的為其下一級的目錄,那么分目錄就需要更改其對應的applicationName。
QSettings settings(QSettings::NativeFormat, QSettings::UserScope, QString("%1\\%2").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()), "Qt5.5");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.5");
QSettings settings2(QString("%1\\%2").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()), "Qt5.6");
settings2.setValue("Name", "Qt Creator");
settings2.setValue("Version", "5.6");
分組
替換applicationName的方式看起來有些繁瑣,相比之下,使用group分組則會更簡單!
QSettings settings;
settings.beginGroup("Qt5.5");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.5");
settings.endGroup();
settings.beginGroup("Qt5.6");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.6");
settings.endGroup();
這時,我們再次查看注冊表數據。
注:
新建目錄,則需要重新打開注冊表,如果新添加設置,則不需要重新打開注冊表,只需要來回切換對應的選項即可。
讀寫配置文件
一般存儲
如上,我們只需要將格式從NativeFormat變為IniFormat即可:
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", 5);
這時,我們打開對應的存儲目錄,數據就生成了。
我們可以進入文件夾:C:\Users\WangLiang\AppData\Roaming
(AppData默認為隱藏文件,需要設置顯示才可查看),可以看到生成了文件夾”Digia”以及配置文件”Qt.ini”。
一般讀取
存儲完數據之后,默認的程序啟動時需要加載對應的數據。
QString strName = settings.value("Name").toString();
int nVersion = settings.value("Version").toInt();
//Name:Qt Creator Version:5
這時,我們可以通過查看應用程序輸出窗口得到輸出結果。
分組存儲
我們可以看到配置文件中包含默認的分組為:General。通常情況下,我們需要對配置進行歸類,例如:用戶名、密碼等信息屬於用戶組,產品名稱、版本號屬於設置組。
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
settings.beginGroup("Setting");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", 5);
settings.endGroup();
settings.beginGroup("User");
settings.setValue("UserName", "WangL");
settings.setValue("Password", "123456");
settings.endGroup();
這時我們再次查看配置文件,里面已經生成了另外兩個分組。
分組讀取
settings.beginGroup("Setting");
QString strName = settings.value("Name").toString();
int nVersion = settings.value("Version").toInt();
settings.endGroup();
//Name:Qt Creator Version:5
settings.beginGroup("User");
QString strUserName = settings.value("UserName").toString();
QString strPassword = settings.value("Password").toString();
settings.endGroup();
//UserName:WangL Password:123456
分目錄存儲
什么時候需要分目錄存儲呢?QQ大家都用過吧,是不是每一個用戶都有一個對應QQ號的目錄呢,里面保存各個用戶對應的信息。
如上,我們可以看出,organizationName對應的本地路徑為C:\Users\WangLiang\AppData\Roaming\Digia
,applicationName對應的為其下的配置文件,那么如果我們需要在同一路徑下建立多個目錄就需要更改對應的organizationName,配置文件名稱則需要更改其對應的applicationName了。
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QString("%1\\%2\\%3").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()).arg("Qt5.5"), "User");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.5");
QSettings settings2(QSettings::IniFormat, QSettings::UserScope, QString("%1\\%2\\%3").arg(QCoreApplication::organizationName()).arg(QCoreApplication::applicationName()).arg("Qt5.5"), "User");
settings2.setValue("Name", "Qt Creator");
settings2.setValue("Version", "5.6");
這時,我們再次查看本地文件,則會發現C:\Users\WangLiang\AppData\Roaming\Digia\Qt
所在目錄下會生成兩個文件夾”Qt5.5”和”Qt5.6”,並且每一個目錄底下會生成對應的配置文件User.ini。
刪除內容
刪除一個指定的鍵
QSettings settings;
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", 5);
settings.remove("Name");
QStringList keys = settings.allKeys();
// keys: ["Version"]
清空所有鍵
settings.clear();
QStringList keys = settings.allKeys();
// keys: []
刪除設置鍵以及子設置鍵
QSettings settings;
settings.setValue("Qt5.6", "5.6");
settings.beginGroup("Qt5.5");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.5");
settings.endGroup();
settings.beginGroup("Qt5.6");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.6");
settings.endGroup();
settings.remove("Qt5.6");
QStringList strList = settings.allKeys();
// keys: ["Qt5.5/Name", "Qt5.5/Version"]
如果key為空字符串,在當前group()的所有鍵將被刪除。
QSettings settings;
settings.setValue("Qt5.6", "5.6");
settings.beginGroup("Qt5.5");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.5");
settings.endGroup();
settings.beginGroup("Qt5.6");
settings.setValue("Name", "Qt Creator");
settings.setValue("Version", "5.6");
settings.endGroup();
settings.beginGroup("Qt5.6");
settings.remove("");
settings.endGroup();
QStringList keys = settings.allKeys();
// keys: ["Qt5.5/Name", "Qt5.5/Version"]
疑問解釋
如上文代碼,我們可以知道未刪除之前keys: ["Qt5.6", "Qt5.5/Name", "Qt5.5/Version", "Qt5.6/Name", "Qt5.6/Version"]
,其中Qt5.6所在分組為默認的General。
那么調用下面代碼:
settings.beginGroup("Qt5.6");
settings.remove("");
settings.endGroup();
應該只刪除對應組中的所有鍵才對,也就是說剩余的keys應該為 ["Qt5.6", "Qt5.5/Name", "Qt5.5/Version"]
,General下的鍵為什么會被刪除呢?好,這里先跳過,繼續。
General下的鍵既然可以被刪除,那么在Qt5.5分組下建立對應的Qt5.6鍵值,應該也會被刪除。
刪除前:
刪除后:
什么鬼,為嘛Qt5.5分組下的Qt5.6對應的鍵還在呢?
我們繼續分析:
刪除前:keys: ["Qt5.6", "Qt5.5/Qt5.6", "Qt5.5/Name", "Qt5.5/Version", "Qt5.6/Name", "Qt5.6/Version"]
。
助手中關於remove()的說明為:Removes the setting key and any sub-settings of key.
也就是說:Qt5.5/Qt5.6鍵中即使存在Qt5.6,但是所屬的setting key為Qt5.5而非Qt5.6,所以不會被刪掉。
既然這樣,那么我們的疑問也就不復存在了。
更多參考
原文作者:一去丶二三里
作者博客:去作者博客空間