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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C/C++】删除链表的倒数第 N 个结点(leetcode T19)

考点预览&#xff1a; 双指针法&#xff1a;通过维护两个指针来一次遍历链表&#xff0c;避免了多次遍历链表的低效方法。 边界条件&#xff1a;要特别处理删除头结点的情况。 题目描述&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回…

人工智能定义

一、人工智能核心概念体系 1.1 人工智能的本质 人工智能的定义:人工智能(Artificial Intelligence,简称 AI)是指计算机系统能够执行通常需要人类智能才能完成的任务,如学习、推理、解决问题、理解自然语言、识别图像和声音等。它通过模拟人类的智能行为,运用算法和数据…

量子计算的威胁,以及企业可以采取的措施

当谷歌、IBM、Honeywell和微软等科技巨头纷纷投身量子计算领域时&#xff0c;一场技术军备竞赛已然拉开帷幕。 量子计算虽能为全球数字经济带来巨大价值&#xff0c;但也有可能对相互关联的系统、设备和数据造成损害。这一潜在影响在全球网络安全领域引起了强烈关注。也正因如…

0—QT ui界面一览

2025.2.26&#xff0c;感谢gpt4 1.控件盒子 1. Layouts&#xff08;布局&#xff09; 布局控件用于组织界面上的控件&#xff0c;确保它们的位置和排列方式合理。 Vertical Layout&#xff08;垂直布局&#xff09; &#xff1a;将控件按垂直方向排列。 建议&#xff1a;适…

【Uniapp-Vue3】导入uni-id用户体系

在uniapp官网的uniCloud中下载uni-id用户体系 或者直接进入加载&#xff0c;下载地址&#xff1a;uni-id-pages - DCloud 插件市场 进入以后下载插件&#xff0c;打开HbuilderX 选中项目&#xff0c;点击确定 点击跳过 点击合并 右键uniCloud文件夹下的database文件夹&#x…

如何免费使用稳定的deepseek

0、背景&#xff1a; 在AI辅助工作中&#xff0c;除了使用cursor做编程外&#xff0c;使用deepseek R1进行问题分析、数据分析、代码分析效果非常好。现在我经常会去拿行业信息、遇到的问题等去咨询R1&#xff0c;也给了自己不少启示。但是由于官网稳定性很差&#xff0c;很多…

VSCode+PlatformIO报错 找不到头文件

如图示&#xff0c;找不到目标头文件 demo工程运行正常&#xff0c;考虑在src文件夹内开辟自己的代码&#xff0c;添加后没有找到 找了些资料&#xff0c;大概记录如下&#xff1a; 1、c_cpp_properties.json 内记录 头文件配置 .vscode 中&#xff0c;此文件是自动生成的&a…

Python 网络爬虫实战全解析:案例驱动的技术探索

Python 网络爬虫实战全解析&#xff1a;案例驱动的技术探索 本文围绕 Python 网络爬虫展开&#xff0c;深入剖析其技术要点&#xff0c;并通过实际案例演示开发流程。从爬虫原理引入&#xff0c;逐步讲解如何使用 Python 中的requests和BeautifulSoup等库进行网页数据抓取与解…

List(3)

前言 上一节我们讲解了list主要接口的模拟实现&#xff0c;本节也是list的最后一节&#xff0c;我们会对list的模拟实现进行收尾&#xff0c;并且讲解list中的迭代器失效的情况&#xff0c;那么废话不多说&#xff0c;我们正式进入今天的学习 list的迭代器失效 之前在讲解vec…

在zotero里部署papaerschat插件,以接入现有大模型

papaerschat插件里集成了openAI的GPT3.5、gpt-4o、gpt-mini大模型以及Claude3、Gemini、Deepseek等大模型。通过接入这些大模型可以辅助我们阅读论文。以部署方式如下&#xff1a; 1.下载zotero的插件市场&#xff0c;用以管理zotero里的插件。下载地址&#xff1a; https://…

Memory Programming ...Error: File does not exist: Max.hex

Memory Programming ... Error: File does not exist: Max.hex 原因 删了确定就可以了

渗透测试【seacms V9】

搭建seacms环境 我选择在虚拟机中用宝塔搭建环境 将在官网选择的下载下来的文件解压后拖入宝塔面板的文件中 创建网站 添加站点 搭建完成seacmsV9 找到一个报错口 代码分析 <?php set_time_limit(0); error_reporting(0); $verMsg V6.x UTF8; $s_lang utf-8; $dfDbn…

仅需三分钟,使用Vue3.x版本组件式风格实现一个消息提示组件!

一、前言 在日常的前端项目开发中&#xff0c;我们时常需要使用到“消息提示”&#xff08;以下简称“消息”&#xff09;这个组件来帮助我们更好的给予用户提示&#xff0c;例如常见的“登录成功”、“操作成功”、“服务器异常”等等提示。 尽管市面上已经有一些组件库提供了…

敏捷开发实践指南:从理论到落地的全面解析

敏捷工程&#xff1a;现代软件开发的变革与实践 近年来&#xff0c;软件工程领域经历了从传统瀑布模型到敏捷开发的深刻转变。这种转变不仅是技术方法的升级&#xff0c;更是团队协作、需求管理和交付模式的革新。本文将从敏捷开发的核心理念、主流方法、实践案例及未来趋势等…

期权帮|股指期货基差和价差有什么区别?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 股指期货基差和价差有什么区别&#xff1f; 一、股指期货基差 股指期货基差是指股指期货价格与其对应的现货指数价格之间的差额。 股指期货基差计算公式&#xff1a;基差 现…

【论文解读】《C-Pack: Packed Resources For General Chinese Embeddings》

论文链接&#xff1a;https://arxiv.org/pdf/2309.07597 本论文旨在构建一套通用中文文本嵌入的完整资源包——C-Pack&#xff0c;解决当前中文文本嵌入研究中数据、模型、训练策略与评测基准缺失的问题。论文主要贡献体现在以下几个方面&#xff1a; 大规模训练数据&#xf…

ARM 处理器平台 eMMC Flash 存储磨损测试示例

By Toradex秦海 1). 简介 目前工业嵌入式 ARM 平台最常用的存储器件就是 eMMC Nand Flash 存储&#xff0c;而由于工业设备一般生命周期都比较长&#xff0c;eMMC 存储器件的磨损寿命对于整个设备来说至关重要&#xff0c;因此本文就基于 NXP i.MX8M Mini ARM 处理器平台演示…

html中的元素(2)

在用块级元素完成网页的组织和布局以后&#xff0c;要为其中的每一个小区块添加内容&#xff0c;就需要用到行内元素&#xff1a; 1.字体样式元素 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title>HTML5 保留的文本格式元…

代码随想录二刷|动态规划12

dp动态规划 动态规划五步曲 动态规划数组的含义 dp[i] 递推公式 动态规划数组的初始化 确定遍历顺序 手动模拟验证 动态规划遇到问题要打印dp数组&#xff0c;看和模拟结果哪里不一样 一 基础问题 斐波那契数 题干 斐波那契数 &#xff08;通常用 F(n) 表示&#xf…

linux 系统 安装禅道教程

禅道&#xff08;ZenTao&#xff09;是一款开源的项目管理软件&#xff0c;特别适用于敏捷开发和团队协作。它集成了需求管理、任务管理、缺陷管理、版本管理、文档管理等功能&#xff0c;旨在帮助团队更高效地管理项目&#xff0c;提升工作协同和开发效率。 禅道的主要特点&a…