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

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.mzph.cn/news/896665.shtml

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

相关文章

解锁浏览器内置API,助力跨标签/跨页面数据通信

1 BrodcastChanner 概念 BroadcastChannel接口表示给定源的任何浏览上下文都可以订阅的命名频道。它允许同源的不同浏览器窗口、标签页、frame 或者 iframe 下的不同文档之间相互通信。消息通过message事件进行广播&#xff0c;该事件在侦听该频道的所有BroadcastChannel对象上…

Mysql-如何理解事务?

一、事务是什么东西 有些场景中&#xff0c;某个操作需要多个sql配合完成&#xff1a; 例如&#xff1a; 李四这个月剩下的前不够交房租了&#xff0c;找张三借1000元急用&#xff1a; &#xff08;1&#xff09;给张三的账户余额 减去1000元 updata 账户表 set money money -…

《deepseek FlashMLA :高效的 MLA 解码内核》:此文为AI自动翻译

FlashMLA GitHub - deepseek-ai/FlashMLA FlashMLA 是适用于 Hopper GPU 的高效 MLA 解码内核&#xff0c;针对可变长度序列服务进行了优化。 当前发布&#xff1a; BF16、FP16块大小为 64 的分页 kvcache 快速开始 安装 python setup.py install 基准 python tests/test_fl…

Windows对比MacOS

Windows对比MacOS 文章目录 Windows对比MacOS1-环境变量1-Windows添加环境变量示例步骤 1&#xff1a;打开环境变量设置窗口步骤 2&#xff1a;添加系统环境变量 2-Mac 系统添加环境变量示例步骤 1&#xff1a;打开终端步骤 2&#xff1a;编辑环境变量配置文件步骤 3&#xff1…

蓝桥杯 之 填空题-位运算与循环

文章目录 循环握手问题门牌制作-循环小球反弹幸运数艺术与篮球跑步 位运算3个1美丽的2024 位运算 可以关注这个Lowbit(x) 如何判断最低位是否是1&#xff1f; num&1 1就说明num最低位是1 循环 循环 握手问题 握手问题 思路分析&#xff1a; 可以直接计算出来&#xff…

Java进阶——反射机制超全详解

反射能在运行时动态操作类和对象的能力&#xff0c;极大地增强了程序的灵活性。但是反射的使用也伴随着性能开销和安全风险。本文将由博主带你一起深入探讨 Java 反射的核心概念、关键类和方法&#xff0c;以及在日常开发中的应用场景。 本文目录 一、反射的核心概念1. 运行时类…

OAK相机的抗震性测试

在工业环境中&#xff0c;双目视觉相机必须具备与工作环境同等的坚固性。鉴于部分客户会将我们的相机应用于恶劣环境&#xff08;例如安装在重型机械上&#xff09;&#xff0c;我们依据EN 60068-2-6:2008标准对相机进行了振动耐受性测试。 测试涉及的相机型号包括&#xff1a…

Express MVC

1. 安装依赖 npm init -y npm install express npm install --save-dev typescript ts-node ejs types/node types/express tsc --init 2. 项目目录结构如下&#xff0c;没有的手动创建 /my-app/src/modelsuser.ts/viewsindex.ejsuserList.ejs/controllersuserController.ts…

apache-maven-3.2.1

MAVEN_HOME D:\apache-maven-3.2.1 PATH D:\apache-maven-3.2.1\bin cmd mvn -v <localRepository>d:\localRepository</localRepository> setting.xml <?xml version"1.0" encoding"UTF-8"?><!-- Licensed to the Apache Soft…

合并两个有序链表:递归与迭代的实现分析

合并两个有序链表&#xff1a;递归与迭代的实现分析 在算法与数据结构的世界里&#xff0c;链表作为一种基本的数据结构&#xff0c;经常被用来解决各种问题。特别是对于有序链表的合并&#xff0c;既是经典面试题&#xff0c;也是提高编程能力的重要练习之一。合并两个有序链…

破解密码防线:渗透测试中的密码攻击手法汇总

密码是网络安全中的一道重要防线&#xff0c;然而&#xff0c;若密码策略不严密&#xff0c;往往会为攻击者提供可乘之机。本文将简要介绍渗透测试中关于密码的几种常见攻击思路和手法。 1. 确认使用默认及常见的账号密码 在渗透测试的初期&#xff0c;攻击者通常会尝试使用系…

CSS Selectors

当然&#xff0c;理解纯CSS选择器&#xff08;CSS Selectors&#xff09;对于进行UI自动化测试非常重要。CSS选择器允许您通过元素的属性、层级关系、类名、ID等来精准定位页面上的元素。下面我将详细讲解CSS选择器的常见用法&#xff0c;并结合您的需求提供具体的示例。 1. 基…

【java】@Transactional导致@DS注解切换数据源失效

最近业务中出现了多商户多租户的逻辑&#xff0c;所以需要分库&#xff0c;项目框架使用了mybatisplus所以我们自然而然的选择了同是baomidou开发的dynamic.datasource来实现多数据源的切换。在使用初期程序运行都很好&#xff0c;但之后发现在调用com.baomidou.mybatisplus.ex…

浅入浅出Selenium DevTools

前言 在自动化测试领域&#xff0c;Selenium一直是主流工具之一。随着前端技术的不断发展&#xff0c;浏览器的功能也在不断丰富。 Selenium 3版本前&#xff0c;一套通用的采集流程如上图所示&#xff1a; 打开Charles&#xff0c;设置Session自动导出频次及导出路径Seleniu…

04 路由表的IP分组传输过程

目录 1、路由表的核心结构 2、IP分组传输过程和数据包转发过程 2.1、IP分组传输过程 2.2、数据包转发过程 2.3、IP分组传输过程和数据包转发的区别 3、数据包的变化 3.1、拓扑结构 3.2、传输过程详解&#xff08;主机A → 主机B&#xff09; 3.2.1、主机A发送数据 3.2…

【子网掩码计算器:Python + Tkinter 实现】

子网掩码计算器&#xff1a;Python Tkinter 实现 引言代码功能概述代码实现思路1. 界面设计2. 功能实现3. 事件处理 子网掩码计算器实现步骤1. 导入必要的库2. 定义主窗口类 SubnetCalculatorApp3. 创建菜单栏4. 创建界面组件5. 判断 IP 地址类别6. 计算子网信息7. 其他功能函…

【练习】【贪心】力扣1005. K 次取反后最大化的数组和

题目 1005 K 次取反后最大化的数组和 给你一个整数数组 nums 和一个整数 k &#xff0c;按以下方法修改该数组&#xff1a; 选择某个下标 i 并将 nums[i] 替换为 -nums[i] 。 重复这个过程恰好 k 次。可以多次选择同一个下标 i 。 以这种方式修改数组后&#xff0c;返回数组 可…

3dsmax中使用python创建PBR材质并挂接贴图

前言 笔者处理模型时下载到一个pbr材质库贴图包&#xff0c;手动每次创建材质过于麻烦&#xff0c;因此计划使用自动化脚本根据贴图名自动创建材质。 3dsmax的原本脚本使用的是maxscript&#xff0c;语法有点奇怪懒得学&#xff0c;发现也支持使用python编写脚本&#…

Metal学习笔记九:光照基础

光和阴影是使场景流行的重要要求。通过一些着色器艺术&#xff0c;您可以突出重要的对象、描述天气和一天中的时间并设置场景的气氛。即使您的场景由卡通对象组成&#xff0c;如果您没有正确地照亮它们&#xff0c;场景也会变得平淡无奇。 最简单的光照方法之一是 Phong 反射模…

JAVA学习笔记038——bean的概念和常见注解标注

什么是bean? Bean 就是 被 Spring 管理的对象&#xff0c;就像工厂流水线上生产的“标准产品”。这些对象不是你自己 new 出来的&#xff0c;而是由 Spring 容器&#xff08;一个超级工厂&#xff09;帮你创建、组装、管理。 由 Component、Service、Controller 等注解标记的…