Qt-中⽂乱码原因以及解决⽅法
本⽂主要分析了基于windows系统msvc2013编译器的Qt中⽂乱码。
概念
字库表:是⼀个系统⽀持的⽂字,符号,数字的集合。
unicode字符转中文编码字符集(字符集):我们平时所说的字符集就是这个,计算机以⼆进制的形式存储字符,每个字符对应的⼆进制编码不同,⽽编码字符集就是所有编码与字符的映射集合。
例如:在ASCII码的编码字符集中,字母A的编码是65,65的⼆进制就是01000001。
字符编码:不同字符的编码不同,其⼆进制的位数也不同。为了达到节省空间,解析⽅便等⽬的,出现了多种存储字符编码的⽅式,每种⽅式对应⼀套算法也称字符编码。
例如:Unicode字符集,utf-8,utf-16字符编码。
源⽂件字符集:源⽂件本⾝也是⽂本⽂件,所以源⽂件字符集是指源⽂件保存时采⽤哪种字符编码。
执⾏字符集:可执⾏应⽤程序内使⽤何种字符编码。编译器会将源码字符集转换为执⾏字符集。
注意:
1、当MSVC2013编译程序的时候,会分析源⽂件采⽤何种编码,有BOM标识符则可以正确识别其编码,若没有BOM标识符则认为其使⽤本地字符编码local字符集。我们使⽤的windows系统本地字符编码为GBK编码。
2、编译器分析出源⽂件字符编码之后,会进⾏解码再编码,将源字符集转码成执⾏字符集。执⾏字符集⼀般默认为使⽤本地字符编码local 字符集,也可以进⾏设置。
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就会出现乱码。)
中⽂乱码测试
使⽤如下⽅法进⾏测试:⾸先创建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)。因此三者都显⽰乱码。
中⽂乱码解决⽅法
综上所述,解决Qt5中⽂乱码的⼀个⽐较好的⽅式,源⽂件设置BOM标识的utf-8编码,执⾏字符集为设置为utf-8。这样源字符集,执⾏字符集都是⼀致。