qt vs 中文乱码

14 篇文章 1 订阅

QString显示中文乱码的原因:

Qt5中QString内部采用unicode字符集,utf-16编码。构造函数QString::QString(const char *str)默认使用fromUtf8()将str所指的执行字符集从utf-8转码成utf-16。
由上面fromUtf8()可知,QString需要执行字符集编码为utf-8,然后以utf-8进行解码,再编码为utf-16才能获得正确的字符编码。显示中文乱码的原因其实就QString转码方式与执行字符集不一致。(比如,源字符集为本地字符集GBK编码,QString以utf-8的方式进行解码,会导致获得错误的二进制编码,再将错误二进制转为utf-16就会出现乱码。)

解决方法

1、把Qt Creator 或者 vs 的 IDE的环境设置为“UTF-8+BOM”编码。

2、所有源文件和头文件都保存为“UTF-8+BOM”编码。

3、预编译头文件加入

#if defined(_MSC_VER) && (_MSC_VER >= 1600)    
# pragma execution_character_set("utf-8")    
#endif

或者添加 QMAKE_CXXFLAGS += /utf-8 到pro文件中

 

qt设置“UTF-8+BOM”

Windows环境下, Qt Creator, 菜单->工具->选项->文本编辑器->行为->文件编码->默认编码, 推荐utf-8 ,使用“如果编码是UTF-8则添加bom”

vs设置“UTF-8+BOM”

  • 单击“工具”|“自定义”命令,弹出“自定义”对话框。
  • 单击“命令”标签,进入“命令”选项卡。
  • 在“菜单栏”下拉列表中,选择“文件”选项。
  • 单击“添加命令”按钮,弹出“添加命令”对话框。
  • 在“类别”列表中,选择“文件”选项;在“命令”列表中,选择“高级保存选项”选项。
  • 单击“确定”按钮,关闭“添加命令”对话框。
  • 选中“控件”列表中的“高级保存选项”选项,单击“上移”或者“下移”按钮,调整该命令的位置。
  • 单击“关闭”按钮,完成“高级保存选项”命令的添加操作。

把高级保存功能调用出来,就可以将文件保存为“unicode(utf-8 带签名)”。

中文乱码分析

1. Qt Creator的编辑器默认使用UTF-8(代码页65001)编码来读取文本文件。而Visual Studio保存文件时默认采用的是本地编码,对于简体中文的Windows操作系统,这个编码就是GB2312(代码页936)。如果使用Qt Creator读取由Visual Studio创建的文件,那么编辑器就会以UTF-8编码格式读取GB2312编码格式的文件,出现中文乱码。至于英文部分不会乱码,是因为UTF-8和GB2312在单字节字符部分是兼容的。

2. MSVC在编译时,会根据源代码文件有无BOM来定义源码字符集。如果有BOM,则按BOM解释识别编码;如果没有,则使用本地字符集,对于简体中文的Windows操作系统就是GB2312。那么,当MSVC遇到一个没有BOM的UTF-8编码的文件时,它通常会把文件看作GB2312的来处理。如果文件全是英文没有问题,但如果包含中文,编译器就会出现误读。这种情况下,Qt Creator编辑器是正常的。但MSVC编译器会乱码。

 

参考网址

常用的3个编译器(微软VC++的cl编译器,Mingw中的g++,Linux下的g++),源代码分别采用GBK和无BOM的UTF-8以及有BOM的UTF-8这3种编码进行保存,发生的现象如下表所示。

情况1:指的是Local字符集为GBK

情况2:指的是Local字符集为UTF-8

源代码的编码

编译器

显示正常

显示乱码

GBK

win vs cl

情况1

情况2

win mingw-g++

情况1

情况2

linux g++

情况1

情况2

UTF-8(无BOM)

win vs cl

编译失败

error C2001: 常量中有换行符

编译失败
error C2001: 常量中有换行符

win mingw-g++

情况2

情况1

linux g++

情况2

情况1

UTF-8(有BOM)

win vs cl

情况1

情况2(有#pragma预处理)

情况2(没有#pragma预处理)

win mingw-g++

情况2

情况1

linux g++

情况2

情况1

 

字库表:是一个系统支持的文字,符号,数字的集合。
编码字符集(字符集):我们平时所说的字符集就是这个,计算机以二进制的形式存储字符,每个字符对应的二进制编码不同,而编码字符集就是所有编码与字符的映射集合。例如:在ASCII码的编码字符集中,字母A的编码是65,65的二进制就是01000001。
字符编码:不同字符的编码不同,其二进制的位数也不同。为了达到节省空间,解析方便等目的,出现了多种存储字符编码的方式,每种方式对应一套算法也称字符编码。例如Unicode字符集,utf-8,utf-16字符编码。
源文件字符集:源文件本身也是文本文件,所以源文件字符集是指源文件保存时采用哪种字符编码。
执行字符集:可执行应用程序内使用何种字符编码。编译器会将源码字符集转换为执行字符集。

 

中文乱码测试

使用如下方法进行测试:首先创建QString对象str并初始化,因为QString构造函数内部调用了QString::fromUtf8(),所以它俩表现应该一致。QString::fromLocal8Bit()将执行字符集以本地编码转为utf-16。具体代码如下:

例1,创建一个编码为带BOM标识的utf-8源文件,打印如下:

打印前两个发生了乱码,fromLocal8Bit显示正常。源文件带BOM标识,因此编译器可以正确识别源文件字符编码,并以正确地方式将源字符集(utf-8编码)转为执行字符集即local字符集(GBK编码)。此时执行字符集为loacl字符集,而fromUtf8将执行字符集以utf-8方式进行解码,所以会出现乱码。fromLocal8Bit将执行字符集以本地编码进行转码,因此获得正确的字符编码。

例2,创建一个编码为不带BOM标识的utf-8源文件.,打印如下:

打印前两个显示正常,fromLocal8Bit发生了乱码。源文件不带BOM标识,因此编译器会认为源文件编码为本地编码,而执行字符集也是本地编码,因此不会进行转码(本人推测的0.0),但实际上执行字符集是utf-8编码。因此fromUtf8将执行字符集以utf-8进行解码,显示正确;而fromLocal8Bit将执行字符集以本地编码进行解码,显示乱码。
例3,使用预处理命令#pragma execution_character_set(“utf-8”),将执行字符集设置为utf-8。创建一个编码为带BOM标识的utf-8源文件.,打印如下:

打印前两个显示正常,fromLocal8Bit发生了乱码。编译器识别源文件字符编码为utf-8,执行字符集也为utf-8,因此不会转码。fromUtf8可以正确的以utf-8进行解码,显示正确。而fromLocal8Bit将执行字符集以本地编码进行解码,显示乱码。
例4,使用预处理命令#pragma execution_character_set(“utf-8”),将执行字符集设置为utf-8。创建一个编码为不带BOM标识的utf8源文件.,打印如下:

三个显示乱码。编译器识别源文件字符编码为本地编码(实际为utf-8编码),并错误地将源字符集以本地编码进行解码,再编码为utf-8(相当于utf-8以本地编码转码为utf-8)。因此三者都显示乱码。

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值