Qt 4.8.7 + MSVC 中文乱码问题深入分析
此问题很常见,然而网上关于此问题的分析大多不够深刻,甚至有错误;加之Qt5又更改了一些编码策略,而很多文章并未提及版本问题,或是就算提了,读者也不重视。这些因素很容易让读者产生误导。今日我彻底研究透了这个问题,在此记录。
环境:Qt 4.8.7, Qt Creator 4.2.2, MSVC 2015
Qt 4.8.7 + MSVC 的中文乱码问题,实际上有两层原因。
第一层:MSVC 不识别无 BOM 的 UTF-8
Qt Creator 默认源代码文件编码是无BOM的UTF-8,而MSVC编译器会误认为这是本地多字节字符集(MBCS)编码(对于简中地区,即GBK,代码页936)。
解决方法1(推荐):Qt Creator选项—文本编辑器—文件编码—UTF8 BOM——如果编码是UTF8则添加—确定。
解决方法2:Qt Creator选项—文本编辑器—文件编码—默认编码—GBK—确定。
注意:修改以上两种方法提及的设置后,Qt Creator并不会自动修改已保存的文件的编码或BOM。我们需要修改一下含中文的文件,重新Ctrl+S保存,这样才能将这些设置应用于这些文件。
第二层:QString 构造函数默认假定的文本编码不正确
我们代码中的字符串,特别是用于测试这个乱码问题的字符串,一般都是C样式的,即用一对双引号包围的const char []类型字符串字面量,如 "Hello World" 。然而 Qt 里很多函数的参数要求的字符串类型都是 QString,我们填入这种C样式字符串时就会有个隐式转换,转为QString类型,其实也就是QString这个构造函数在帮我们转换:
explicit QString::QString(const char* ch)
然而const char*类型只表明了这个字符串是多字节字符集,却没指明是哪一种,他可能是GBK, UTF-8等等,甚至可能是跟咱这边八竿子打不着的西欧语言字符集Latin-1(ISO-8859-1)。不加声明的话,MSVC默认我们的字符串字面量是本地多字节字符集(MBCS),即GBK编码,如下图左侧“标题title”文本所示情况。而如果在这种C样式字符串的引号前加上“u8”二字,则MSVC就会认为此字符串是UTF-8编码,如下图右侧“文本text”文本所示情况。![]()
MSVC在我们有或没有声明的情况下判断出了此字符串的编码后,对此字符串进行编码,也就是将它们转换为二进制的字节数据,传给QString的构造函数。
注意:
①即使在上一层问题的解决中,我们选择了保留UTF-8,加上BOM供MSVC识别,以上所述MSVC对C样式字符串的编码的解析方式仍然成立。他不会因为你的源码文件是UTF-8编码,就将其中的这种字符串优先视为UTF-8。所以上一层问题你选择了哪种解决方法对这一层问题是没有影响的。
②“u8”标记只是给MSVC编译器的提示,MSVC处理后,不管是加了u8还是没加,一律变成const char[]这样的字节数组。也就是说,有没有u8,QString的构造函数是不知道的,看不见的。他只知道传进来了一个const char* 类型。
传给QString的构造函数后,QString要解码这些二进制数据,也就是将它们映射到可显示(我们能看懂)的字符上。由于这些数据不能体现编码,他就要猜。咱当然希望他猜是GBK啦,但是事与愿违,Qt库毕竟不是中国人写的。他默认猜成西欧语言字符集Latin-1(如图)!这就会导致我们在代码里写了些汉字,却显示出一堆拉丁字母甚至音标。这也是为何在没有QString参与的情况下只解决第一层问题就好了,例如控制台窗口的std::cout,而在需要把const char*转换成QString时就又会出问题。

那么解决思路已经很明显了。要么修改它的设置,让他猜成GBK(或UTF-8),要么明明白白的告诉他我们的字符串是啥编码(使用 QString::fromXXX 函数)。
解决方法1(推荐):在 QApplication 对象创建前将“C样式字符串的编码(CodecForCStrings)”设为UTF-8,并在每个含中文的字符串字面量的前导引号前加上u8二字(如QString str(u8"这是中文");)。设置“C样式字符串的编码”的方法是:在程序的入口点(main函数)中最开始的位置加上图中这句代码(别忘了加头文件):
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

解决方法2: 跟方法1一样修改“C样式字符串的编码”,但设为本地多字节字符集(MBCS,一般是GBK),代码中的字符串字面量不加“u8”(如QString str("这是中文");)。具体方法和上条类似,不再赘述,但main函数中加的那句代码改为:
QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
解决方法3: 在每个字符串字面量的前导引号前加上u8,并用 QString::fromUtf8() 包裹,如图:

解决方法4:字符串字面量的前导引号前不加u8,并用 QString::fromLocal8Bit() 包裹,如图:

依次解决以上两层问题后,中文就不再乱码了。再次强调,本文只针对 Qt 4.8.7 + MSVC2015 环境提供问题原理和解决方案,Qt5就不一样了,说不定微软也会在未来的MSVC中添加对无BOM的UTF-8文件的识别。那时,问题的解决将简单很多。
szx0427 作于 2024/07/17
相关文章:
Qt 4.8.7 + MSVC 中文乱码问题深入分析
此问题很常见,然而网上关于此问题的分析大多不够深刻,甚至有错误;加之Qt5又更改了一些编码策略,而很多文章并未提及版本问题,或是就算提了,读者也不重视。这些因素很容易让读者产生误导。今日我彻底研究透了…...
IDEA的常见代码模板的使用
《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试(Debug) 第七章 …...
arcgis怎么选取某个指定区域地方的数据,比如从全国乡镇数据选取长沙市乡镇数据
一共5个步骤,没一句废话,耐心看完。看完你就会在任何软件选取指定范围的数据了。 一、如图,先将数据加载到arcgis里面,我们要选取里面长沙市的范围数据。 二、选取长沙市的语句 “市” like ‘长沙%’ 切记,切记&…...
二、链表(1)
203.移除链表元素 创建一个虚拟哨兵头节点,就不用考虑原本头结点要不要删除 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def remove…...
KAFKA搭建教程
KAFKA搭建教程 期待您的关注 KAFKA学习笔记 帮助更多人 目录 KAFKA搭建教程 1.下载Kafka并解压 2.添加环境变量 3.修改 server.properties 文件 4.将kafka复制到其它节点 5.修改node1、node2节点的broker.id 6.将master的环境变量同步到node1、 node2 7.启动zookeeper…...
Linux网络——套接字与UdpServer
目录 一、socket 编程接口 1.1 sockaddr 结构 1.2 socket 常见API 二、封装 InetAddr 三、网络字节序 四、封装通用 UdpServer 服务端 4.1 整体框架 4.2 类的初始化 4.2.1 socket 4.2.2 bind 4.2.3 创建流式套接字 4.2.4 填充结构体 4.3 服务器的运行 4.3.1 rec…...
SpringBoot源码深度解析
今天,聊聊SpringBoot的源码,本博客聊的版本为v2.0.3.RELEASE。目前SpringBoot的最新版为v3.3.2,可能目前有些公司使用的SpringBoot版本高于我这个版本。但是没关系,因为版本越新,新增的功能越多,反而对Spri…...
【Qt】常用控件
文章目录 QWidgetenabledgeometrywindow framewindowTitlewindowIconqrc资源管理windowOpacitycursorfonttoolTipfocusPolicystyleSheet 按钮类PushButtonRadioButtonCheckBoxSignals 显示类LabelLCDNumberProgressBarCalendar 输入类LineEditTextEditComboBoxSpinBoxDateTimeE…...
electron 主进程和渲染进程通信
在Electron中,主进程(main process)和渲染进程(renderer process)之间的通信是非常重要的,因为Electron应用通常会将用户界面(由Web技术如HTML, CSS, 和JavaScript构建)和原生功能(如系统对话框、文件I/O等)分开处理。主进程管理应用的生命周期和创建渲染进程,而渲染…...
【ARM】MDK-解决CMSIS_DAP.DLL missing报错
【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 记录解决CMSIS_DAP.DLL missing的报错情况,对应相关报错信息,供后续客户参考,快速解决客户问题。 2、 问题场景 客户进行硬件调试时,发现Target设置内有CMSIS_DAP.DL…...
CSS 的环境变量函数env()
在CSS中,env() 函数并不是传统意义上的“环境变量”函数,如你在编程语言中可能遇到的那样。相反,env() 是CSS中的一个函数,它用于访问由宿主环境(如浏览器)提供给CSS的自定义属性(也称为环境变量…...
数学建模--国赛备赛---TOPSIS算法
目录 1.准备部分 1.1提交材料 1.2MD5码相关要求 2.TOPSIS算法 2.1算法概述 2.2基本概念 2.3算法核心思想 2.4拓展思考 3.适用赛题 3.1适用赛题说明 3.2适用赛题举例 4.赛题分析 4.1指标的分类 4.2数据预处理 4.2.1区间型属性的变换 4.2.2向量规范化 4.3数据加…...
均值滤波算法及实现
均值滤波器的使用场景: 均值滤波器使用于处理一些如上述蓝色线的高斯噪声场景 红色曲线是经过均值滤波处理后的数据。主要因为均值滤波设置数据缓冲区(也即延时周期),使得测量值经过缓冲不会出现特别大的变化。 黄色曲线为高斯噪声…...
【Apache Doris】周FAQ集锦:第 16 期
【Apache Doris】周FAQ集锦:第 16 期 SQL问题数据操作问题运维常见问题其它问题关于社区 欢迎查阅本周的 Apache Doris 社区 FAQ 栏目! 在这个栏目中,每周将筛选社区反馈的热门问题和话题,重点回答并进行深入探讨。旨在为广大用户…...
单例模式_Golang
目录 一、单例模式 1.1 基本概念 1.2 使用场景 二、Golang实现 2.1 懒汉模式(Lazy Loading) 一、单例模式 1.1 基本概念 一个类只能生成一个实例,且该类能自行创建这个实例的一种模式,这个定义个人感觉可以拆的通俗一些,在项目的生命周…...
代码随想录 day 18 二叉树
第六章 二叉树part06 详细布置 530.二叉搜索树的最小绝对差 需要领悟一下二叉树遍历上双指针操作,优先掌握递归 题目链接/文章讲解:https://programmercarl.com/0530.%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91%E7%9A%84%E6%9C%80%E5%B0%8F%E7%B…...
降雨量预测 | Matlab基于ARIMA-RBF降雨量预测
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 降雨量预测 | Matlab基于ARIMA-RBF降雨量预测 注:程序和数据放在一个文件夹。 程序语言为matlab,程序可出预测效果图,指标图; 代码特点:参数化编程、参数可方便更改、代…...
包含示例和模板的流程文档指南
当您的业务扩展时,您会得到越来越多的移动部件,并且需要有人来跟踪复杂性。人员和任务需要以尽可能最高效的方式进行组织,并且您必须找到某种方法让员工知道如何执行有效完成工作所需的流程。 为了使流程可重复,需要对其进行记录…...
51单片机嵌入式开发:15、STC89C52RC操作蜂鸣器实现一个music音乐播放器的音乐盒
STC89C52RC操作蜂鸣器实现一个music音乐播放器的音乐盒 1 概述2 蜂鸣器操作方法3 蜂鸣器发出音声4 硬件电路5 软件实现6 整体工程:7 总结 1 概述 要实现一个基于STC89C52RC单片机的音乐盒,可以按照以下步骤进行: (1)硬…...
B树(B-Tree)数据结构
1. 什么是B树? B树(B-Tree)是一种多路搜索树,用于存储和检索大量数据。它是自适应的,适用于各种存储设备和各种数据量。B树的特点是高效的搜索、插入和删除操作,且可以在各种情况下保持树的平衡。 2. B树…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
