在 windows 系统上使用 qt 开发应用程序时,可能会遇到中文乱码问题。即使 windows 已经全面转向 unicode 编码,但有时仍会因为编码不匹配而出现乱码。以下是详细的分析和解决方案:
alt=”QT 应用程序在 Windows 系统上出现中文乱码” />
Windows 早期采用多字节编码,的确容易出现乱码问题。随着 Windows 全面转向 Unicode 编码,多语言的支持得到了极大改善,出现中文乱码的问题变得较少。出现乱码问题一般是由于 GBK 编码的文件被当做 utf8 编码打开,或者 utf8 编码的文件被当做 GBK 编码打开。这种情况也多出现在 linux 和 Windows 之间交换文件。
最近几个月开始使用 QT 开发应用程序,无论是在 Windows 还是 Linux 系统下,没有特别配置,编写出来的应用程序都能很好地显示各种语言。即使在 Linux 系统中选择英语语言设置,也能正常显示中文、日文等。
然而,今天遇到了一个 QT 应用程序在 Windows 下出现中文乱码的问题,令人措手不及。
具体情况是这样的,QT 代码来自他人,别人提供的可执行程序没有中文乱码问题。但是在我这里编译这个 QT 项目,生成的程序却出现了乱码。
首先,我怀疑代码采用了 GBK 之类的编码,但经过逐一检查,发现都是采用 utf8 编码,使用记事本打开和保存时都能正常显示。通常,采用 utf8 编码是一个非常安全的方案,全程使用 utf8 对多语言的支持是最好的。
那么问题是否出在 Windows 特有的 utf8 bom 上呢?
这里需要提一下,BOM 代表 Byte order mark,即字节序标记,有两个作用:
- 说明字符流属于 Unicode 编码,且表明了编码方式。
- 说明了字节序:big endian 和 little endian。
一般来说,utf8 不需要 BOM,这是微软搞出来的。由于 Windows 是使用最广泛的操作系统,尽管 Linux 程序员极度抵制 utf8 BOM,但也无法阻止它的存在。
但是在 QT 应用程序的乱码问题上,utf8 BOM 并没有什么关系。是否带 BOM 只是文件头几个字节的差异,要么直接出错,不会引起乱码。
而且这个乱码问题还非常奇怪,在 QT 界面设计器中输入的中文显示正常,但是通过 c++ 代码添加的字符串就有乱码问题。难道是字符串类的问题吗?但我在代码中使用的是 QString,内部就是用的 utf8 编码,即使我强行指定 utf8 编码,问题也没有解决。
这个问题我也咨询过 gpt,GPT 给出的方法是检查源码的编码、编辑器的编码设定、使用 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,而没想着去网上搜索。