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树…...
CosyVoice语音生成效果对比:原声vs克隆声,几乎听不出区别
CosyVoice语音生成效果对比:原声vs克隆声,几乎听不出区别 1. 语音克隆技术的新高度 最近测试了CosyVoice语音克隆模型的效果,结果让我大吃一惊。这个由阿里巴巴通义实验室开发的语音生成模型,仅需3-10秒的参考音频就能克隆出几乎…...
【Houdini】HDA参数编辑实战:从基础到高级技巧
1. HDA参数编辑基础入门 第一次打开Houdini的HDA参数面板时,我完全被那些密密麻麻的选项搞懵了。后来才发现,掌握几个核心概念就能轻松上手。HDA(Houdini Digital Asset)是Houdini中最强大的功能之一,它允许我们把复杂…...
领域驱动设计实战:解密DDDSample中Cargo聚合根的黄金法则
领域驱动设计实战:解密DDDSample中Cargo聚合根的黄金法则 【免费下载链接】dddsample-core This is the new home of the original DDD Sample app (previously hosted at sf.net).. 项目地址: https://gitcode.com/gh_mirrors/dd/dddsample-core DDDSample…...
千问3.5-2B辅助MATLAB科学计算:算法实现与结果可视化脚本生成
千问3.5-2B辅助MATLAB科学计算:算法实现与结果可视化脚本生成 1. 科研计算的新助手 作为一名经常使用MATLAB的科研工作者,你是否遇到过这样的困扰:明明知道要解决什么数学问题,却卡在代码实现环节?或者花了大量时间调…...
Swagger Client 与微服务架构:如何管理多个 API 端点的终极方案
Swagger Client 与微服务架构:如何管理多个 API 端点的终极方案 【免费下载链接】swagger-js Javascript library to connect to swagger-enabled APIs via browser or nodejs 项目地址: https://gitcode.com/gh_mirrors/sw/swagger-js 在现代微服务架构中&a…...
Ostrakon-VL-8B终端部署详解:CSS像素级修复+终端打印效果实现原理
Ostrakon-VL-8B终端部署详解:CSS像素级修复终端打印效果实现原理 1. 项目概述与核心价值 Ostrakon-VL-8B是一款专为零售与餐饮场景优化的多模态大模型,我们将其能力封装成了一个具有独特像素艺术风格的Web交互终端。这个终端将复杂的图像识别任务转化为…...
百川2-13B-4bits量化模型+OpenClaw:低成本自动化办公方案实测
百川2-13B-4bits量化模型OpenClaw:低成本自动化办公方案实测 1. 为什么选择量化模型OpenClaw组合 去年我接手了一个需要处理大量邮件的项目,每天要花3小时在重复性回复上。当我尝试用OpenClaw自动化流程时,发现原版大模型的显存占用让我的R…...
别再花钱买模板了!用扣子(Coze)和剪映,5分钟搞定城市宣传视频(保姆级节点配置)
零成本打造城市宣传片:Coze剪映全流程实战指南 想象一下这样的场景:你刚接手一个本地文旅推广项目,预算只够买两杯咖啡,但甲方期待的是《航拍中国》级别的视觉大片。传统解决方案要么外包烧钱,要么自己熬夜学剪辑到崩溃…...
别再被网站当机器人了!手把手教你编译一个‘隐身版’Chromedriver(绕过Selenium检测)
从源码到隐身:深度定制Chromedriver绕过检测的工程实践 当你的Selenium脚本突然被目标网站拦截,熟悉的"Access Denied"页面赫然出现时,那种挫败感每个爬虫开发者都深有体会。网站的反爬系统越来越智能,常规的UserAgent轮…...
【GD32F407】内部Flash高效读写策略与实战优化
1. GD32F407内部Flash特性解析 GD32F407作为国产MCU中的明星产品,其内部Flash设计颇具特色。第一次拿到芯片手册时,我发现它的存储架构比想象中复杂得多。最让我印象深刻的是前512KB空间的零等待特性——这意味着在此范围内的代码执行速度堪比RAM&#x…...
