INI文件读写操作:

# include <QSettings>

QString str;
// 打开INI配置文件(指定为IniFormat格式)
QSettings iniTest("E:\\test.ini",QSettings::IniFormat);

添加修改键值: 如果键值/节点不存在则添加,/后第一个值表示结点名称

iniTest.setValue("/IP/ipv4","192.168.10.150");
[IP]
ipv4=192.168.10.150

删除键值: 当结点下的最后一个键值对被删除后,结点也会被删除

iniTest.remove("/IP/ipv4");

读键值: 直接指定路径,如果不存在,则返回默认值(可省略)

iniTest.Value("/IP/ipv4", "Error").toString();

遍历读键值

// 获取节点列表
QStringList groupList = iniTest.childGroups();
    
// 遍历节点
foreach(QString group,groupList)
{
    iniTest.beginGroup(group);
    
    ui->textBrowser->append(group);
    
    // 获取当前结点下的键值列表
    QStringList keyList = iniTest.childKeys();
    // 遍历列表
    foreach(QString key,keyList)
    {
        // 读取键值
        str = key + "="+tr(iniTest.value(key).toString().toStdString().c_str());
        ui->textBrowser->append(str);
    }
    iniTest.endGroup();
}

注册表操作

打开注册表(指定为NativeFormat格式)

QSettings reg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP",QSettings::NativeFormat);

获取当前路径下的项目列表:

// 获取当前路径下的项目列表
QStringList groupsList=reg.childGroups();
// 遍历列表
foreach(QString group,groupsList)
{
    ui->comboBox->addItem(group);
    reg.beginGroup(group);            // 开始操作本项目(切换路径)
    // 在此插入其他操作
    reg.endGroup();                   // 离开当前项目,返回上级
}

获取当前路径下的键值列表:*

// 获取当前路径下的键值列表(不包含子项)
QStringList keyList = reg.childKeys();
// 获取当前路径下的键值列表(包含子项)
// QStringList keyList = reg.allKeys();

foreach(QString key,keyList)
{
    ui->textBrowser->append(key + " = " + reg.value(key).toString());
}

foreach(QString group,groupsList)
{
    ui->comboBox->addItem(group);
}

删除键值: 需要以管理员身份运行

reg.remove("Serial1");

注意事项:

QT5不支持带/的键名操作(可以读出键名,但不能通过键名取键值),需要通过WinAPI来实现;
只支持字符串,32bit及64bit类型的值,其他类型读出为空,WinAPI可以读出所有类型。

WinAPI示例:

#include <qt_windows.h>

QSettings reg("HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM",QSettings::NativeFormat);

HKEY  hKey;
//打开启动项Key
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
{
    qDebug() << "windows api read reg failed!";
}
else{
    qDebug() << "windows api read reg success";
}

//for(int i = 0; i < reg.childKeys().size(); ++i)
//{
//    QString key = reg.childKeys().at(i);

QStringList keyList = reg.childKeys();
foreach(QString key , keyList)
{
    DWORD dwSize = 1024;      
    DWORD dwType = REG_DWORD;
    WCHAR buf[1024];
    
    QString backslash_key = key.replace(QChar('/'), QChar('\\'));
    //char * 转换为 wchar_t * 类型
    const wchar_t * w_key = reinterpret_cast<const wchar_t *>(backslash_key.utf16());

    DWORD dwRet  = RegQueryValueEx(hKey, w_key, NULL, &dwType, (LPBYTE)(&buf), &dwSize);

    if (ERROR_SUCCESS != dwRet)
    {
         qDebug() << "RegQueryValueEx failed " << dwRet;
         break;
    }
    else
    {
         if(dwType == REG_SZ)  //字符串类型
         {
              QString strMessage = QString::fromUtf16(reinterpret_cast<const ushort *>(buf), dwSize/2 - 1);
              qDebug() << "dwSize is: " << dwSize << "value is: " << strMessage;
         }

         else if(dwType == REG_BINARY)
         {
            qDebug() << "REG_BINARY dwSize is" << dwSize;
         }

         else if(dwType == REG_QWORD)
         {
             qDebug() << "REG_DWORD  value = " << reinterpret_cast<const qint32 *>(buf);
         }
         else if(dwType == REG_QWORD)
         {
             qDebug() << "REG_QWORD  value = " << reinterpret_cast<const qint64 *>(buf);
         }
         else
         {
             qDebug() << "dwType ==" << dwType << "dwSize = " << dwSize;
             // 通过dwSize获取数据长度,数据全在buf里
         }
    }
}

RegCloseKey(hKey);

1.reinterpret_cast<const qint32 > 用于强制转换,相当于(qint32*),但直接用指针强制转换的话,qt5编译器会抱怨。
2.部分文档要求在工程文件中加入LIBS += -lAdvapi32静态库,实际测试不加入也可以正常编译运行,如果有问题就加上去。
3.WinAPI会造成系统依赖,但是....., 除了Windows,还有谁会用到注册表呢?