qt5的中文乱码问题,QString、QStringLiteral 为 UTF-16 编码

news2025/2/28 3:46:40

qt5的中文乱码问题一直没有很明确的处理方案。

今天处理进程间通信时,也遇到了qt5乱码问题,一边是设置的GBK,一边设置的是UTF8,单向通信约定采用UTF8。
发送端保证发的是UTF8字符串,因为UTF8在网络数据包中没有字节序问题。
问题出在发送端,字符串的原始编码不明确,转换方案一直靠猜,咨询多个AI助手,也都是胡乱猜测,没有一个能解决,没有一个能给出确定解释。类似于,在一个陌生环境,自己不知道自己在哪。

转机出现在,某个AI突然说了两句话:
QString内部是UTF-16 编码。
QStringLiteral可以确保字符串是UTF-16 编码。

这个关键信息,类似地图中的关键参考点,从确定的参考点出发,每一步都确定转换出来的数据是什么编码,不就可以解决乱码问题了吗?

于是,解决方案就明确了:
发送端:

NetSendFunction(QString message=QStringLiteral("中文法文..."));
QByteArray data = message.toUtf8();

data确定是UTF8编码,作为网络数据包的一部分发送出去。

接收端:

QString message = QString::fromUtf8(data);

QString QStringLiteral 源码

为了预防AI胡说误导,稍微调查一下qt源码:

typedef QTypedArrayData<ushort> QStringData; //数组中存的是ushort是关键点
class Q_CORE_EXPORT QString {
public:
    typedef QStringData Data;
    ...    
    Data *d;//实际存储str的地方
#define QT_UNICODE_LITERAL(str) u"" str // 关键点在u这个C++前缀
#define QStringLiteral(str) \
    ([]() noexcept -> QString { \
        enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
        static const QStaticStringData<Size> qstring_literal = { \
            Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
            QT_UNICODE_LITERAL(str) }; \
        QStringDataPtr holder = { qstring_literal.data_ptr() }; \
        const QString qstring_literal_temp(holder); \
        return qstring_literal_temp; \
    }()) \
    /**/

C++标准规定u前缀生成UTF-16,确保跨编译器的一致性。 所以核心是c++规范起了作用,各种编译器实现必须满足这一结果。
这种前缀类似运算符号。 用户也可以自定义这种前缀,它会触发函数调用。

其它细节:
QStringLiteral,这个宏用于在编译时创建一个QString对象,以提高运行时效率。
使用立即调用的lambda表达式,在编译时生成静态的QStaticStringData实例qstring_literal 。
qstring_literal_temp通过持有QStringDataPtr的临时QString对象,直接引用静态数据,无需动态内存分配或拷贝,提升效率。

补充deepseek给出的参考

在 Qt5 中,QString 的内部编码始终是 UTF-16。这是 Qt 框架设计的核心特性之一,目的是统一处理 Unicode 字符。以下是详细解释和验证方法:


1. QString 的内部编码是 UTF-16

  • UTF-16 的特性
    • 每个基本字符由 16 位(即一个 QChar)表示。
    • 对于 Unicode 中超出 基本多语言平面(BMP, U+0000 到 U+FFFF) 的字符(如 Emoji 或某些汉字),Qt 会使用 代理对(Surrogate Pairs),即两个 QChar 表示一个字符。
  • Qt 官方文档的明确说明

    “QString stores a string of 16-bit QChars, where each QChar corresponds to one Unicode 4.0 character.”
    (摘自 Qt 5.15 文档)


2. 为什么选择 UTF-16?

  • 跨平台一致性:UTF-16 能够覆盖绝大多数现代语言的字符,同时平衡内存占用和性能。
  • 与操作系统 API 兼容:Windows 原生 API 使用 UTF-16,Qt 选择此编码可以高效与之交互,避免转换开销。

3. 如何验证 QString 的编码?

方法 1:观察字符存储方式

通过检查 QString 中字符的存储长度和代理对的存在,可以间接验证 UTF-16 编码。例如:

QString str = u"𠮷"; // 这是一个超出 BMP 的字符(U+20BB7)
qDebug() << str.length(); // 输出 2,因为使用了代理对
方法 2:查看内存布局

通过调试器查看 QString 的内存,可以看到每个字符占 16 位:

QString str = "Hello";
const QChar *data = str.data();
// 在调试器中查看 data 数组,每个元素为 16 位
方法 3:转换到其他编码

通过 toUtf8()toLatin1() 等方法的转换行为,可以间接确认内部编码:

QString str = u"Ä"; // Unicode 字符 U+00C4
qDebug() << str.toUtf8();   // 输出 UTF-8 编码的字节序列:0xC3 0x84
qDebug() << str.toLatin1(); // 输出 Latin-1 编码的字节:0xC4

4. 注意事项

  • 与源码编码无关QString 的内部编码是固定的 UTF-16,与源代码文件编码(如 UTF-8、GBK)无关。例如:
    // 无论源码是 UTF-8 还是 GBK,以下字符串都会被正确转换为 UTF-16
    QString str = "你好";
    
  • 转换函数的用途toUtf8()fromLocal8Bit() 等方法用于与外部数据(如文件、网络)交互时进行编码转换,不影响 QString 内部存储。

5. 总结

  • QString 内部编码固定为 UTF-16,开发者无需动态判断。
  • 若需要处理其他编码的数据(如 UTF-8、GBK),需通过转换方法(如 QString::fromUtf8())与 QString 交互。
  • 对于超出 BMP 的字符,Qt 会自动使用代理对,确保兼容性。

参考文档:QString Class | Unicode in Qt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2307167.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第2章_保护您的第一个应用程序

第2章_保护您的第一个应用程序 在本章中&#xff0c;您将学习如何使用 Keycloak 保护您的第一个应用程序。为了让事情更有趣&#xff0c;您将运行的示例应用程序由两部分组成&#xff0c;前端 Web 应用程序和后端 REST API。这将向您展示用户如何向前端进行身份验证&#xff0…

【Godot4.3】自定义圆角容器

概述 Godot控件想要完全实现现代UI风格&#xff0c;需要进行大量的自定义组件设计。本篇就依托于笔者自己对现代UI设计中的圆角面板元素模仿来制作圆角容器组件。 圆角容器 圆角元素在现代的扁平UI设计中非常常见&#xff0c;在Godot中可以通过改进PanelContainer来或者自定…

Flutter系列教程之(5)——常用控件Widget的使用示例

目录 1.页面跳转 2.某个控件设置点击事件 3.AlertDialog对话框的使用 4.文本输入框 5.按钮 圆角扁平按钮: 圆角悬浮按钮: 6.补充 圆点 7.布局使用 Row控件左右对齐 调整边距 1.页面跳转 首先&#xff0c;先介绍一下页面跳转功能吧 Flutter使用 Navigator 进行页面…

DeepSeek开源周,第三弹再次来袭,DeepGEMM

在大型模型推理中&#xff0c;矩阵乘法&#xff08;GEMM&#xff09;是计算的核心瓶颈。DeepGEMM 应运而生——一款专为 FP8精度矩阵乘法 设计的轻量级CUDA库&#xff0c;由深度求索&#xff08;DeepSeek&#xff09;团队开源。它凭借极简代码&#xff08;核心仅300行&#xff…

stm32四种方式精密控制步进电机

在搭建完clion的开发环境后&#xff0c;我决定重写之前的项目并优化完善&#xff0c;争取做出完全可落地的东西&#xff0c;也结合要写的论文内容一同学习下去。 因此&#xff0c;首当其冲的就是回到步进电机控制领域&#xff0c;把之前使用中断溢出进行步进电机控制的方案进行…

git merge -s ours ...的使用方法

当我们在自己的feature branch上开发时&#xff0c;并且已经commit&#xff0c;push了好几次 同时develop分支也commit , push了好几次&#xff0c; 如下图所示 这个时候就不能直接将feature branch上的改动 pull request到develop上面&#xff0c;因为develop基线已经不一样了…

数字可调控开关电源设计(论文+源码)

1 设计要求 在本次数字可调控开关电源设计过程中&#xff0c;对关键参数设定如下&#xff1a; &#xff08;1&#xff09;输入电压&#xff1a;DC24-26V,输出电压&#xff1a;12-24&#xff08;可调&#xff09;&#xff1b; &#xff08;2&#xff09;输出电压误差&#xf…

【DeepSeek】【GPT-Academic】:DeepSeek集成到GPT-Academic(官方+第三方)

目录 1 官方deepseek 1.1 拉取学术GPT项目 1.2 安装依赖 1.3 修改配置文件中的DEEPSEEK_API_KEY 2 第三方API 2.1 修改DEEPSEEK_API_KEY 2.2 修改CUSTOM_API_KEY_PATTERM 2.3 地址重定向 2.4 修改模型参数 2.5 成功调用 2.6 尝试添加一个deepseek-r1参数 3 使用千帆…

DeepSeek R1 + 飞书机器人实现AI智能助手

效果 TFChat项目地址 https://github.com/fish2018/TFChat 腾讯大模型知识引擎用的是DeepSeek R1&#xff0c;项目为sanic和redis实现&#xff0c;利用httpx异步处理流式响应&#xff0c;同时使用buffer来避免频繁调用飞书接口更新卡片的网络耗时。为了进一步减少网络IO消耗&…

Android移动应用开发实践-1-下载安装和简单使用Android Studio 3.5.2版本(频频出错)

一、下载安装 1.Android Studio3.5.2下载地址&#xff1a;Android Studio3.5.2下载地址 其他版本下载地址&#xff1a;其他版本下载地址 2.安装教程&#xff08;可以多找几个看看&#xff09; 安装 | 手把手教你Android studio 3.5.2安装&#xff08;安装教程&#xff09;_a…

Rk3568驱动开发_驱动编写和挂载_2

1.字符驱动介绍&#xff1a; 字符驱动&#xff1a;按照字节流镜像读写操作的设备&#xff0c;读写数据分先后顺序&#xff0c;例如&#xff1a;点灯、按键、IIC、SPI、等等都是字符设备&#xff0c;这些设备的驱动叫字符驱动设备 Linux应用层如何调用驱动&#xff1a; 字符设…

【苍穹外卖】问题笔记

【DAY1 】 1.VCS找不到 好吧&#xff0c;发现没安git 接着发现安全模式有问题&#xff0c;点开代码信任此项目 2.导入初始文件&#xff0c;全员爆红 好像没maven&#xff0c;配一个 并在设置里设置好maven 3.启用注解&#xff0c;见新手苍穹 pom.xml改lombok版本为1.1…

1.1部署es:9200

安装es&#xff1a;root用户&#xff1a; 1.布署java环境 - 所有节点 wget https://d6.injdk.cn/oraclejdk/8/jdk-8u341-linux-x64.rpm yum localinstall jdk-8u341-linux-x64.rpm -y java -version 2.下载安装elasticsearch - 所有节点 wget ftp://10.3.148.254/Note/Elk/…

上传securecmd失败

上传securecmd失败 问题描述&#xff1a;KES V8R6部署工具中&#xff0c;节点管理里新建节点下一步提示上传securecmd失败&#xff0c;如下&#xff1a; 解决办法&#xff1a; [rootlocalhost ~]# yum install -y unzip 上传的过程中会解压&#xff0c;如果未安装unzip依赖包…

C++:dfs,bfs各两则

1.木棒 167. 木棒 - AcWing题库 乔治拿来一组等长的木棒&#xff0c;将它们随机地砍断&#xff0c;使得每一节木棍的长度都不超过 5050 个长度单位。 然后他又想把这些木棍恢复到为裁截前的状态&#xff0c;但忘记了初始时有多少木棒以及木棒的初始长度。 请你设计一个程序…

P9420 [蓝桥杯 2023 国 B] 子 2023

P9420 [蓝桥杯 2023 国 B] 子 2023 题目 分析代码 题目 分析 刚拿到这道题&#xff0c;我大脑简单算了一下&#xff0c;这个值太大了&#xff0c;直观感觉就很难&#xff01;&#xff01; 但是&#xff0c;你仔仔细细的一看&#xff0c;先从最简单的第一步入手&#xff0c;再…

2025-02-26 学习记录--C/C++-C语言 判断字符串S2是否在字符串S1中

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; C语言 判断字符串S2是否在字符串S1中 #include <stdio.h> // 引入标准输入输出库&#xff0c;用于使用 printf 等函数 #…

游戏引擎学习第124天

仓库:https://gitee.com/mrxiao_com/2d_game_3 回顾/复习 今天是继续完善和调试多线程的任务队列。之前的几天&#xff0c;我们已经介绍了多线程的一些基础知识&#xff0c;包括如何创建工作队列以及如何在线程中处理任务。今天&#xff0c;重点是解决那些我们之前没有注意到…

组件的组成和组件的嵌套关系

组件的组成 首先建一个.vue文件&#xff0c;在里面写一个内容&#xff1a; <template> <div><div class"container">{{ message }}</div> </div> </template> <script> export default{data(){return{message:"组件…

2025 PHP授权系统网站源码

2025 PHP授权系统网站源码 安装教程&#xff1a; PHP7.0以上 先上传源码到服务器&#xff0c;然后再配置伪静态&#xff0c; 访问域名根据操作完成安装&#xff0c; 然后配置伪静态规则。 Ngix伪静态规则&#xff1a; location / { if (!-e $request_filename) { rewrite …