Qt显示汉字乱码问题

转载自http://blog.csdn.net/u012790503/article/details/52485263

测试1

新建test工程用于测试,main.c文件内容如下:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString str_hanzi("百度"); // 汉字
    QString str_ascii("baidu.com"); // 字母

    qDebug() << str_hanzi;
    qDebug() << str_ascii;

    return a.exec();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

运行, 输出结果如下: 
这里写图片描述

不出意料的乱码。

下面开始分析。

此时,源代码main.c的编码是UTF-8 BOM。 
这里写图片描述

使用Notepad++查看,编码也是UTF-8 BOM。说明的确是UTF-8编码。

查看目标文件main.obj,目标文件路径如下: 
这里写图片描述

使用Notepad++打开,搜索”百度”二字,结果如下: 
这里写图片描述
同时可以看到此时Notepad++显示文件内容使用的编码是ANSI,即本地编码,可以正确的显示汉字。那就说明,编译生成*.obj目标文件时,编译器将源码中的字符串由UTF-8 BOM转换成了本地编码。

接下来查看test.exe的内容,同样搜索”百度”二字,如下图: 
这里写图片描述
和理论一样,因为.exe文件就是.obj文件链接起来生成的。

到此为止,我们可以看到,源码中的汉字字符串在生成可执行文件的过程中被转换成了本地编码(实际上不止汉字,字母也会被转换)。

那么和乱码有什么关系呢? 
我们知道,Qt内部是使用Unicode编码的,即QString保存的是Unicode编码的字符串。所有使用QString的函数都认为QString内部是Unicode字符串。 
那么,当test.exe执行的时候,它在读取”百度”二字的时候,它认为该字符串是Unicode编码,而实际上呢?是本地编码。乱码问题发生的时机就在于此。 
这样一来,乱码的根本原因就一目了然了。

那么,那些QTextCodec类以及QString::fromLocal8bit的作用和原理是什么呢?

先说QSring::fromLocal8bit吧,这个比较简单,意思就是从一个本地编码的字符串生成一个QString字符串(Unicode),这样的话,将该字符串传递给其他函数,就不会出现乱码了。实验之,首先修改程序如下:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString str_hanzi("百度"); // 汉字
    QString str_ascii("baidu.com"); // 字母

    qDebug() << QString::fromLocal8Bit("百度"); // 修改了此处
    qDebug() << str_ascii;

    return a.exec();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

输出结果: 
这里写图片描述 
可以看到它实现了汉字的正常的显示,和理论相同。

那么QTextCodec这个类是做什么的呢? 
顾名思义,它的中文名应该是”文本编码转换器”(Text coding converter),下面是网上流传的一段代码:

QTextCodec *codec = QTextCodec::codecForName("GBK");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
 
 
  • 1
  • 2
  • 3
  • 4

下面修改程序:

#include <QCoreApplication>

#include <QDebug>
#include <QTextCodec>
#include <QFile>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTextCodec *codec = QTextCodec::codecForName("GBK");
    QTextCodec::setCodecForTr(codec);

    QString str_hanzi("百度"); // 汉字
    QString str_ascii("baidu.com"); // 字母


    qDebug() << QString::fromLocal8Bit("百度");
    qDebug() << str_ascii;
    qDebug() << QObject::tr("百度");

    return a.exec();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

输出结果: 
这里写图片描述

可以看到,这种方法也能实现正确显示汉字。 
但是这种方法的原理是什么? 
关键在于QObject::tr()函数。它是翻译函数(translate),同时会进行编码转换。它的默认行为是认为传入的参数是Unicode编码,不需要转换。当你在程序中添加了设置tr编码格式的代码(如上面的程序,设置为GBK)时,会导致编码从你指定的编码(GBK)转换成Unicode。如果把上面的程序中的GBK改成UTF-8,则会乱码,因为该字符串的真正编码是本地编码GBK。实验结果如下图: 
这里写图片描述

同理,如果将本地编码设置成其他编码,修改代码如下

#include <QCoreApplication>
#include <QDebug>
#include <QTextCodec>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QTextCodec::setCodecForLocale(codec);

    QString str_hanzi("百度"); // 汉字
    QString str_ascii("baidu.com"); // 字母


    qDebug() << QString::fromLocal8Bit("百度");
    qDebug() << str_ascii;
    qDebug() << QObject::tr("百度");

    return a.exec();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

这样的话,使用QString::fromLocal8bit的转换就会不正确,结果如下图: 
这里写图片描述

出乎意料的是,tr的转换也出错了。将UTF-8改回GBK,tr也还是乱码: 
这里写图片描述

于是添加一行QTextCodec::setCodecForTr(codec);,则显示正确。它们之间会相互干扰,这是我们没有预料到的,不过还好这不是什么大问题,可以通过显式设置来纠正。

结论

说了那么多,总结如下: 
1、exe中的字符串编码始终是本地编码,与源代码文件的编码无关。 
2、Qt内部需要使用Unicode编码的字符串才能正确处理(显示等操作)。 
3、由于二者不同,所以对于汉字来说,必须经过转换,第一是通过QString::fromLocal8bit函数来转换,第二是通过QTextCodec来转换。但是setTextCodecForTr、setTextCodecForLocale在高版本已被移除。

注意: 
上述测试使用的是Qt4.8.5 msvc2010的版本。minGW还未测试,如果能直接在生成exe文件时直接生成Unicode字符串,那就不需要转换了。

另外还有一种防止乱码的方法,此种方法也可以解决国际化问题导致的乱码,就是使用翻译文件。在源码中统一使用英文。在翻译文件中实现不同版本的语言。

不得不提最后一种比较高级的方法:QStringLiteral宏。它可以直接生成Unicode字符串保存在可执行文件中的只读区域。这样运行时不会发生任何转换。可以显著提高程序运行效率。 
测试代码如下:

#include <QCoreApplication>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString str_ascii("baidu.com"); // 字母

    qDebug() << QStringLiteral("a百度a");
    qDebug() << str_ascii;

    return a.exec();
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

生成的可执行文件再也找不到”百度”二字了。

但是QStringLiteral需要编译器支持,如支持C++11就具有这种特性。Qt高版本一般也支持。具体性能方面的影响请看Qt的帮助文档。

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
智慧农业是一种结合了现代信息技术,包括物联网、大数据、云计算等,对农业生产过程进行智能化管理和监控的新模式。它通过各种传感器和设备采集农业生产中的关键数据,如大气、土壤和水质参数,以及生物生长状态等,实现远程诊断和精准调控。智慧农业的核心价值在于提高农业生产效率,保障食品安全,实现资源的可持续利用,并为农业产业的转型升级提供支持。 智慧农业的实现依赖于多个子系统,包括但不限于设施蔬菜精细化种植管理系统、农业技术资料库、数据采集系统、防伪防串货系统、食品安全与质量追溯系统、应急追溯系统、灾情疫情防控系统、农业工作管理系统、远程诊断系统、监控中心、环境监测系统、智能环境控制系统等。这些系统共同构成了一个综合的信息管理和服务平台,使得农业生产者能够基于数据做出更加科学的决策。 数据采集是智慧农业的基础。通过手工录入、传感器自动采集、移动端录入、条码/RFID扫描录入、拍照录入以及GPS和遥感技术等多种方式,智慧农业系统能够全面收集农业生产过程中的各种数据。这些数据不仅包括环境参数,还涵盖了生长状态、加工保存、检验检疫等环节,为农业生产提供了全面的数据支持。 智慧农业的应用前景广阔,它不仅能够提升农业生产的管理水平,还能够通过各种应用系统,如库房管理、无公害监控、物资管理、成本控制等,为农业生产者提供全面的服务。此外,智慧农业还能够支持政府监管,通过发病报告、投入品报告、死亡报告等,加强农业产品的安全管理和质量控制。 面对智慧农业的建设和发展,存在一些挑战,如投资成本高、生产过程标准化难度大、数据采集和监测的技术难题等。为了克服这些挑战,需要政府、企业和相关机构的共同努力,通过政策支持、技术创新和教育培训等手段,推动智慧农业的健康发展。智慧农业的建设需要明确建设目的,选择合适的系统模块,并制定合理的设备布署方案,以实现农业生产的智能化、精准化和高效化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值