当前位置: 首页 > article >正文

【QT常用技术讲解】QSettings把中文输入到配置文件

前言

        在 QT 中,使用 QSettings 时,默认是将字符串以 Unicode 格式存储,而不是以 UTF-8 编码直接写入配置文件。因为涉及到配置文件,有些时候,配置信息由界面端进行写操作,而后台服务进程进行读取并处理,碰巧便于维护的要求,某些配置项需要中文时,就需要设置为UTF-8格式存储。

QSettings特性

1、默认以 Unicode 格式存储;

2、受特殊字符影响,比如①内容包含逗号','时,读出的配置内容为空;②内容包含分号';'时,读出的配置内容被截断。如果想要读取,配置内容需要加上引号"";

3、配置项不能为中文,比如QString confstr = settings.value("哈哈").toString();取不到值。

如果配置文件配置项/配置内容,比较复杂,不建议使用QSetting,使用原生的文件读取操作:逐行读取->=号分割->匹配关键字->返回内容项(文章末尾提供源码)。

功能讲解

QString设置UTF-8编码

#include <QSettings>
#include <QDebug>

void MainWindow::saveconfmsg(){
    QSettings settings("config.ini", QSettings::IniFormat);//打开文件
    
    QString savestr="测试";
    // 保存中文字符
    settings.setValue("ChineseText", savestr);
}

void MainWindow::getconfmsg(){
    QSettings settings("config.ini", QSettings::IniFormat);//打开文件

    // 读取中文字符
    QString confText = settings.value("ChineseText").toString();
    qDebug() << confText ;

}

通常,如果配置文件的配置项只是QT界面端进行调用的话,以上的保存和读取函数已经够用了,但此时config.ini配置文件中保存的内容是Unicode编码,如下图所示:

而且在测试过程中还发现了会出现多加上了双引号的情况,此时只需要设置为UTF-8方式,即可解决此类问题,代码如下:

#include <QSettings>
#include <QDebug>

void MainWindow::saveconfmsg(){
    QSettings settings("config.ini", QSettings::IniFormat);//打开文件
    
    settings.setIniCodec("UTF-8");//-------设置为UTF-8方式

    QString savestr="测试";
    // 保存中文字符
    settings.setValue("ChineseText", savestr);
}

void MainWindow::getconfmsg(){
    QSettings settings("config.ini", QSettings::IniFormat);//打开文件

    settings.setIniCodec("UTF-8");//-------设置为UTF-8方式

    // 读取中文字符
    QString confText = settings.value("ChineseText").toString();
    qDebug() << confText ;

}

另外,本人测试了QTextCodec的方式无效

QTextCodec *codec = QTextCodec::codecForName("UTF-8");

 Unicode转utf-8

如果界面端已经把中文以Unicode编码方式写入到配置文件,后台服务程序又是普通的C++程序,这时就需要进行Unicode转utf-8

#include <vector>
#include <iomanip>
#include <chrono>
#include <string>
#include <dlfcn.h>
#include <sstream>
#include <fstream>
// 将 Unicode 码点转换为 UTF-8 字符串
std::string unicodeToUtf8(unsigned int codepoint) {
    std::string utf8;
    if (codepoint <= 0x7F) {
        utf8.push_back(static_cast<char>(codepoint));
    } else if (codepoint <= 0x7FF) {
        utf8.push_back(static_cast<char>((codepoint >> 6) | 0xC0));
        utf8.push_back(static_cast<char>((codepoint & 0x3F) | 0x80));
    } else if (codepoint <= 0xFFFF) {
        utf8.push_back(static_cast<char>((codepoint >> 12) | 0xE0));
        utf8.push_back(static_cast<char>(((codepoint >> 6) & 0x3F) | 0x80));
        utf8.push_back(static_cast<char>((codepoint & 0x3F) | 0x80));
    } else {
        utf8.push_back(static_cast<char>((codepoint >> 18) | 0xF0));
        utf8.push_back(static_cast<char>(((codepoint >> 12) & 0x3F) | 0x80));
        utf8.push_back(static_cast<char>(((codepoint >> 6) & 0x3F) | 0x80));
        utf8.push_back(static_cast<char>((codepoint & 0x3F) | 0x80));
    }
    return utf8;
}

// 解析 Unicode 字符串并转换为 UTF-8
std::string convertUnicodeStringToUtf8(const std::string& input) {
    std::string result;
    bool bflag=false;
    char flag1='\\';
    char flag2='x';
    size_t strlen=input.size();
    for(size_t i=0;i<strlen;i++){
        char ch=input[i];
        if(ch==flag1) {
            bflag=true;
            continue;
            //printf("i=%ld\n",i);
        }
        if(bflag==true && ch==flag2){
            if(((i+2)<strlen && input[i+3]==flag1)||(i+3)==strlen){//数字类型:\x31\x32\x33
                std::string hexStr = input.substr(i + 1, 2);
                unsigned int codepoint = std::stoul(hexStr, nullptr, 16);  // 转换为整数
                std::cout << hexStr << "=>" << unicodeToUtf8(codepoint) << std::endl;
                i+=2;
                result+=unicodeToUtf8(codepoint);
            }else if((i+5)<=strlen){
                std::string hexStr = input.substr(i + 1, 4);
                unsigned int codepoint = std::stoul(hexStr, nullptr, 16);  // 转换为整数
                //std::cout << hexStr << "=>" << unicodeToUtf8(codepoint) << std::endl;
                i+=4;
                result+=unicodeToUtf8(codepoint);
            }
        }else{
            bflag=false;
            //printf("i=%ld ch=%c\n",i,ch);
            result+=ch;
        }
    }
    //std::cout << "=>" << result << std::endl;
    return result;
}


int main(){
   Getbaseinfo(CONFIGPATH);//需要自己实现
   std::string utf8_hanzistr = convertUnicodeStringToUtf8(conf_hanzistr);//====转码

}

注:以上的convertUnicodeStringToUtf8()未去掉双引号。

QFile读取配置文件方式

#include <QFile>
#include <QTextStream>
#include <QDebug>
QString getconfmsgbyflag(const QString& flag){
    QString result;
    QFile file(CONFPATH); // 创建文件对象
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { // 打开文件
        qDebug() << "无法打开文件!";
        return result;
    }
    QTextStream in(&file); // 创建文本流
    in.setCodec("UTF-8");
    while (!in.atEnd()) { // 逐行读取
        QString line = in.readLine(); // 读取一行
        qDebug() << line; // 输出每一行
        QStringList conflist = line.split("=");
        if(conflist.size()!=2) continue;
        QString conf_flag=conflist[0];
        QString conf_msg=conflist[1];
        if(conf_flag==flag){
            result=conf_msg;
            break;
        }
    }
    file.close(); // 关闭文件
    return result;
}


http://www.kler.cn/a/405167.html

相关文章:

  • 动态规划子数组系列一>等差数列划分
  • C# 数据结构之【树】C#树
  • k8s 集群安装
  • 什么是RESTful API,有什么特点
  • 分布式数据库中间件可以用在哪些场景呢
  • c++--------《set 和 map》
  • Nuxt.js 应用中的 webpack:configResolved事件钩子
  • 二叉树遍历相关算法题|后序遍历非递归|下到上左到右层次遍历|先序遍历非递归(C)
  • QT简单设计 网格布局 QT5.12.3环境 C++实现
  • 【pytorch-04】:线性回归案例(手动构建)
  • mongoDB回顾笔记(一)
  • springboot嗨玩旅游网站
  • 11.21 深度学习-tensor常见操作
  • Project指针pointer 作业
  • 【日常经验】Mysql中的某个存储过程中如果有查数据,存数据和删除数据,会自动在一个事务中吗
  • AWTK VSCode 实时预览插件端口冲突的解决办法
  • ubuntu 之 安装mysql8
  • 如何用redis+lua来实现高并发限流,超时数据进行等待
  • 基于Java Springboot北京医疗企业固定资产管理系统
  • HTML5和CSS3新增特性
  • cocos creator 3.8 Node学习 3
  • 【spring】spring单例模式与锁对象作用域的分析
  • 【IOS】Undefined symbol: _OBJC_CLASS_$_PAGFile
  • Java通过calcite实时读取kafka中的数据
  • 学习threejs,通过SkinnedMesh来创建骨骼和蒙皮动画
  • WSL2 ubuntu配置redis