• 总结:Qt读写ini配置文件(QSettings)


    一、ini文件介绍

    .ini 文件是Initialization File的缩写,即初始化文件。

    INI文件被用来对操作系统或特定程序初始化或进行参数设置,以实现不同用户的要求。

    一般不用直接编辑这些.ini文件,应用程序的图形界面即可操作以实现相同的功能。

    在Qt中可以使用QSetting类来实现ini文件的读取和写入。

    二、ini文件格式

    ini文件主要有节(section)、键(key)、键值(value)部分组成。

    节 (section) 用方括号括起来,单独占一行,例如:

    [section]

    键(key)又名属性(property),单独占一行用等号连接键名和键值,例如:

    name=value

    例子

    1. [Section1 Name]   
    2. KeyName1=value1   
    3. KeyName2=value2   
    4. ...   
    5. [Section2 Name]   
    6. KeyName21=value21   
    7. KeyName22=value22

    其中:[Section1 Name]用来表示一个段落。

    因为INI文件可能是项目中共用的,所以使用[Section Name]段名来区分不同用途的参数区。

    注意:使用分号表示(;)。在分号后面的文字,直到该行结尾都全部为注解。

    三、QSettings

    Qt通过QSettings类读写ini文件。

    QSettings的存储设置,每个设置都由一个QString和一个QVariant组成,

    QString指定设置的名称(键),QVariant存储与该键关联的数据。 

    1. 头文件:QSetting.h
    2. QSetting读写ini文件的步骤为:
    3. * 通过路径名称打开文件并设定为ini文件格式
    4. * 读/写数据
    5. * 关闭文件,删除句柄

    QSettings::Format有两种:

    QSettings::NativeFormat在windows平台可以读写windows注册表;

    QSettings::IniFormat可以读写ini格式的配置文件。

    3.1 写ini文件

    1. // 根据ini文件路径新建QSettings类
    2. QSettings m_IniFile = new QSettings("ini文件的路径", QSettings::IniFormat);
    3. //通过setValue函数将键值对放在相对于的节下面
    4. m_IniFile->setValue( "节名" + "/" + "键名", "键对应的值");
    5. delete m_IniFile;
    6. 分组写入
    7. //根据ini文件路径新建QSettings类
    8. QSettings m_IniFile = new QSettings("ini文件的路径", QSettings::IniFormat);
    9. m_IniFile ->beginGroup("节名"); // 设置当前节名,代表以下的操作都是在这个节中
    10. m_IniFile->setValue( "键名", "键对应的值"); // 因为上面设置了节了,这里不在需要把节名写上去
    11. m_IniFile.endGroup(); // 结束当前节的操作
    12. delete m_IniFile;

    1. //Qt中使用QSettings类读写ini文件
    2. //QSettings构造函数的第一个参数是ini文件的路径,第二个参数表示针对ini文件,第三个参数可以缺省
    3. QSettings *configIniWrite = new QSettings("config.ini", QSettings::IniFormat);
    4. //向ini文件中写入内容,setValue函数的两个参数是键值对
    5. //向ini文件的第一个节写入内容,ip节下的第一个参数
    6. configIniWrite->setValue("/con/ip", "192.168.0.1");
    7. //向ini文件的第一个节写入内容,ip节下的第二个参数
    8. configIniWrite->setValue("/con/name", "aa");
    9. //向ini文件的第二个节写入内容,port节下的第一个参数
    10. configIniWrite->setValue("port/open", "2222");
    11. configIniWrite->setValue("port/ports", "2222,111,33,444");
    12. //写入完成后删除指针
    13. delete configIniWrite;
    14. 生成文件 config.ini
    15. [con]
    16. ip=192.168.0.1
    17. name=aa
    18. [port]
    19. open=2222
    20. ports="2222,111,33,444"

    3.2 读ini文件

    1. //通过Value函数将节下相对应的键值读取出来
    2. QString value = m_IniFile->Value( "节名" + "/" + "键名").toString;
    3. //打开文件并指定为ini格式
    4. QSettings* configIni = new QSettings(file_path, QSettings::IniFormat);
    5. QString qTemp = "";
    6. //读指定节点的指定数据,其中“Log”为节点,save_days为具体数据项
    7. logDays = configIni->value("Log/save_days").toInt();
    8. qTemp = configIni->value("Log/print_debug").toString();
    9. printDbgLog = qTemp.compare("true", Qt::CaseInsensitive) == 0 ? true : false;
    10. //删除指针,此处未关联父对象,必须手动删除,否则有内存泄露风险
    11. delete configIni;
    12. 分组读取
    13. settings.beginGroup("Setting");
    14. QString strName = settings.value("Name").toString();
    15. int nVersion = settings.value("Version").toInt();
    16. settings.endGroup();
    17. //Name:Qt Creator Version:5
    18. settings.beginGroup("User");
    19. QString strUserName = settings.value("UserName").toString();
    20. QString strPassword = settings.value("Password").toString();
    21. settings.endGroup();
    22. //UserName:WangL Password:123456

    1. [conn]
    2. name=aaa
    3. ip="192.168.1.10"
    4. auto_con=1
    5. speed=50
    6. joints=0.000,-13.959,2.2,83.3,0.000,18.000,-30.000
    7. tcp_offset= 133.4,0.0,0.0,0.0,0.0,-10.0
    8. 读配置文件
    9. QSettings setting("config.ini",QSettings::IniFormat);
    10. setting.setIniCodec("utf-8");// 解决乱码
    11. QString name =setting.value("conn/name").toString();
    12. int speed =setting.value("conn/speed").toInt();
    13. qDebug() << name;
    14. qDebug() << speed;
    15. 输出:
    16. "aaa"
    17. 50

    四、问题总结

    4.1 QSettings写入数据丢失

    在实际使用中,QSettings的写操作在某些情况下会丢失数据。

    尤其在嵌入式Liunx环境中,通过断电方式关机,更容易丢失数据。

    原因分析:

    1,Qt的保存机制是先写到一个临时文件中,然后定时去同步到磁盘,所以不能实时生效。

    2,setValue函数设置指定KEY的值,若该值已存在则替换先前的值,但不立即回写文件。

    3,QSettings类的sync方法并不能立刻同步到磁盘上,需要使用系统sync或syncFlushFileBuffers进行同步。

    解决措施:

    1,在写完后调用QSettings的函数settings.sync();

    2,调用Linux系统的shell命令system("sync");

    1. #include <QtCore/QtCore>
    2. #include <QSettings>
    3. #include <QFile>
    4. #include <QDebug>
    5. #include <QTextCodec>
    6. void ConfigSetting(void)
    7. {
    8. //文件路径+文件名
    9. QString fileName = QCoreApplication::applicationDirPath() + "/Config.ini";
    10. //创建配置目标,输入文件路径,文件格式
    11. QSettings *setting = new QSettings(fileName , QSettings::IniFormat);
    12. //设置文件编码,配置文件中使用中文时,这是必须的,否则乱码
    13. setting->setIniCodec(QTextCodec::codecForName("UTF-8"));
    14. // 判断文件是否存在
    15. if(QFile::exists(fileName)){// 文件存在,读出配置项
    16. // 这里的setting->value的第二参数,是配置项缺省值,即当读取的配置项不存在时,读取该值
    17. // User是配置组,name和age是配置项
    18. QString name = setting->value("User/name", "张三").toString();
    19. int age = setting->value("User/age", 30).toInt();
    20. }else {// 文件不存在,写入配置项,生成配置文件
    21. setting->setValue("User/name", "张三");
    22. setting->setValue("User/age", 30);
    23. // setValue只是把配置项写入了缓冲区,若要写入文件,还需执行同步
    24. // 不同步,无法写入文件,无法生成文件
    25. setting->sync();
    26. system("sync");//将内核缓冲写入文件(磁盘)
    27. }
    28. delete setting;
    29. }

    4.2 QSettings读取ini配置文件乱码

    QSetting中的key值与项目标题如果用中文的话,打开会是乱码。

    QSetting中变量值中如果包含分号,则值字符串需要用双引号(" ")来引用,

    否则取值时候,只会取值到该变量第一个分号之前的内容。

    4.3 QSettings保存float 类型数据时乱码

    使用QSettings 将 float 类型的数据写入到ini时

    float dx = 1.0;

      sParamSetting->setValue("SectionData/d_correct",dx);

    ini文件中内容如下:

    d_correct=@Variant(\0\0\0\x87\xbeH\xb4\x39)

    这是因为 QSettings在写float类型时有点问题,可以将float强制转化为double就可以了。

    也可以将变量设置为double dx = 1.0;

    sParamSetting->setValue("SectionData/d_correct", (double)(sCorrectParam.lcz_correct));

    资料来源

    https://www.cnblogs.com/qianxiaoPro/p/15623881.html

    https://www.cnblogs.com/xiangtingshen/p/11145974.html

    https://blog.csdn.net/yinyuchen1/article/details/75093895

    https://www.cnblogs.com/mzy-google/p/5162107.html

    https://blog.csdn.net/qq_33485434/article/details/80483883

    https://blog.csdn.net/weixin_40583088/article/details/104660595

  • 相关阅读:
    如何解释”字面量“?
    Ansible-自动运维工具
    第九章 动态规划 part15(编辑距离专题) 392. 判断子序列 115. 不同的子序列
    TensorFlow实现线性回归
    独处是一种修行
    编译KArchive在windows10下
    Java实战发包到远程maven仓库
    持续集成/持续部署(3)Jenkins(2)
    快速理解DDD领域驱动设计架构思想-基础篇 | 京东物流技术团队
    Vue ref & props & mixin
  • 原文地址:https://blog.csdn.net/VistaTech/article/details/137710199