Windows 早期采用多字节编码,的确容易出现乱码问题。随着 Windows 全面转向 Unicode 编码,多语言的支持得到完美解决,出现中文乱码的问题就很少出现。出现乱码问题一般是 GBK 编码的文件当做 utf8 编码打开,或者 utf8编码的文件当做 GBK 编码打开。这种情况也多出现在 Linux 和 Windows 之间交换文件。
这几个月开始使用 QT 开发应用程序,不管是 Windows,还是 Linux 系统下,没怎么去特意配置,编写出来的应用程序不管哪国语言,都显示得挺好。甚至在 Linux 系统语言选择英语,也可以正常显示中文、日文等。
但是今天碰到一个 QT 应用程序中文乱码问题,而且还是在 Windows 下,搞得措不及手。
情况是这样的,QT 代码是别人的,别人给的可执行程序也没有中文乱码问题。但是这个 QT 项目在我这边编译,编出来的程序就有乱码问题。
我先是怀疑代码采用了 GBK 之类的编码,但是逐一检查,都是采用的 utf8,使用记事本打开,保存,都能显示正常。一般来说,采用 ut8编码是一个非常保险的方案。全程使用 utf8,对多语言的支持最好。
那问题是不是出在 Windows 下特有的 utf8 BOM 上呢?
这里提一下,BOM 代表 Byte order mark,也就是字节序标记,有2个作用:
1. 说明字符流属于Unicode编码,且表明了编码方式
2. 说明了字节序:big endian 和 little endian
一般来说,utf8不需要 BOM,纯粹是微软搞出来的。鉴于 Windows 是使用最广泛的操作系统,尽管 Linux 程序员极度抵制 utf8 BOM,但也阻止不了。
但在 QT 应用程序乱码问题上,和 utf8 BOM 并没有什么关系,是否带 BOM 只是文件头几个字节的差异,要么直接出错,不会引起乱码。
而且这个乱码问题还非常奇怪,在 QT 界面设计器中输入的中文显示正常,但是通过 C++代码添加的字符串就有乱码问题。难不成是字符串类的问题,但是我在代码中使用的 QString,内部就是用的 utf8编码,即使我强行指定 utf8编码,问题也没解决。
这个问题我也问过 GPT,GTP 给的方法也是检查源码的编码,编辑器的编码设定,使用QString 的编码转换方法等等,都没效果。
中文乱码问题可能只会出现在中文世界,可能中国程序员碰到的几率会更大,于是我就上网搜索吧。使用 “QT 中文乱码”作为关键词,果然搜到一堆反映这个问题的。其中一篇文章讲到:
在 Qt Creator 中使用 MSVC 编译器编译项目时,若处理不当容易出现中文字符串乱码问题。 例如,程序运行时,LabInfo显示的汉字就会出现乱码。
void MainWindow::Changed()
{
QString str="测试";
ui->LabInfo->setText(str);
}
这是因为Qt Creator保存的文件使用的是UTF-8编码(是任何平台、任何语言都可以使用的跨平台的字符集),MSVC编译器虽然可以正常编译带BOM的UTF-8编码的源文件,但是生成的可执行文件的编码是 Windows 本地字符集,比如 GBK2312。
也就是在可执行文件中,字符串“测试”是以GBK2312编码的,而可执行程序执行到这条语句时,对这个字符串却是以UTF-8解码的,这样就会出现乱码。
解决方案之一:
在pro文件中添加
win32:msvc{
QMAKE_CXXFLAGS += /source-charset:utf-8 /execution-charset:utf-8
}
按照文章提供的方法,很快解决了界面上的中文乱码问题。
不过我还是有点不明白,之前创建 QT 应用程序也没有加这个选项,也没见出问题。为啥这个工程就会出问题。
继续查问题,我发现在 QT 应用程序中链接 userlib32,如果不指定上面的编译选项,就会有乱码问题。看来问题出在链接 Windows 库上面,所以保险的方法就是加上编译选项,强行指定源码和可执行程序都使用 utf8编码。
最后,还有一点需要注意,如果调用第三方库,在返回字符串的时候,可能不是采用的 utf8,这个时候需要显式转换编码,否则也可能出现乱码。
程序开发中经常会出现莫名其妙的问题,问题虽然小,但如果以前没碰到过,解决起来也挺费时间的,所以在这里记录一下,也许以后还会碰到类似的问题。
另外解决问题时也不能过度依赖 GPT,这次就是查 GPT,而没想着去网上搜索。