2.3 Qt中文乱码

 在编写qt程序时,将中文字符赋值给QString对象,有时候会出现中文乱码的现象,QString本身是采用unicode编码的,因此是不存在中文支持问题的,所以这种问题并不是 QString 本身的问题,而是没有将正确的字符串赋给QString对象。
 举例来说,”我是汉字”这个字符串,它本身是传统的 char 类型的窄字符串,我们将这个字符串赋值给QString对象时,会存在一个编码的过程,毕竟对于机器来说只能识别0和1,但究竟会使用那种编码方式,这个就和qt版本有关了,在qt4.0的版本中,默认会使用Latin-1编码,这种编码方式是不能识别汉字的,因此“我是汉字”四个字符就会被编码成为我们所能看到的乱码存储到QString对象中,所以问题就出在很多用户对自己当前的编码没太多概念,看一个简单的 Qt 程序:

#include <QApplication>
#include <QTextCodec>
#include <QString>

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

    QString  *e = new QString("我是汉字");
    QString  *f = new QString(QString::fromLocal8Bit("我是汉字"));
    QString  *h = new QString("\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97");
    qDebug() << *e << *f << *h ;

    QApplication a(argc, argv);

    return a.exec();
}

 结果e显示的为乱码,f,h显示的是正常的汉字,当然这个结果是在qt4.0版本中测试的结果,qt5.0版本是不存在这种问题的,至于为什么?我会在后面介绍,这里我先介绍qt4.0的情况。
 在qt4.0中QString对象赋值的时候,遇到字符串时默认的采用了Latin-1编码,于是
QString *e = new QString("我是汉字");
就成了乱码。而

QString *f = new QString(QString::fromLocal8Bit("我是汉字"));
因为我在编码的时候显示的告诉QString对象我要使用Local8Bit进行编码,这种编码方式是支持中文的,因此显示的时候不是乱码。
至于
QString *h = new QString("\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97");其实这句话的含义和下面这句
QString *f = new QString(QString::fromUtf8("我是中文"))
是一样的,因为采用utf8将“我是中文”编码之后的对用16进制字节码就是“\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97”;
 综上所述,只要我们告诉了QString对象我们编码中文字符的方式,就可以避免中文乱码的产生。

 于是就出现了一些方法解决这些问题,QString的成员函数提供了相应的方法来告知QString对象应该按照何种编码来处理 C 字符串

QString QString::fromAscii ( const char * str, int size = -1 )
QString QString::fromLatin1 ( const char * str, int size = -1 ) 
QString QString::fromLocal8Bit ( const char * str, int size = -1 )
QString QString::fromUtf8 ( const char * str, int size = -1 )

 但QString 只提供的这几个成员函数,远远满足不了我们的需求,比如local8Bit是GBK,可是有一个char串是 BIG5 或 Latin-2怎么办?
 于是我们就想到了强大的QTextCodec,当我们把一个char串传给QTextCodec对象后,它就能正确将其编码,并返回相应的QString对象。
QString QTextCodec::toUnicode ( const char * chars ) const
 但这种方法每次都要调用上面的函数,显得有些麻烦,有没有简单的方法呢?答案是肯定的。
 在主程序开头增加如下任意一行,问题就能解决:

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

 两条指令中都设置QString默认采用的编码。一种采用GB2312,一种采用UTF-8,两种编码都可以支持中文字符集,但具体到系统,到底哪一种能起作用,还要看你的系统是否支持相应的编码。

总结下,乱码出现的原因主要是:
 QString内部采用的是 Unicode,它可以同时存放utf8,GBK, BIG5 以及Latin-1等的编码,当你用“我是汉字”生成QString字对象时,牵扯到“我是汉字”如何编码的问题,如果使用utf8或者GBK,存到QString内的字符串就是“我是汉字”,当你使用BIG5或者Latin-1,由于这两种字符集无法识别“我是汉字”这种字符,因此存到QString中的字符串就是一堆乱码。所以要想使QString能显示中文,需要使用能够支持中文的字符集,并告诉QString你使用了那种字符集,在你不告诉它的情况下,qt4.0默认会选择Latin-1,于是8个字”ÎÒÊǺº×Ö”的unicode码被存进了QString中。最终,QString显示的就是一堆乱码。

解决方法:
 网上有很多方法可以告诉QString编码的字符集,如下:

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

 但这在某些情况下也是有问题的,因为程序可能读到系统的中文路径,或者调用中文路径下的外部程序,这时候如果系统是gb2312就有问题了。因为中文路径的编码是采用utf-8存到QString里的,系统解码QString中的中文路径的时候采用的却是系统的gb2312,所以会调不起带中文路径的外部程序。

所以在qt4.0中为了彻底解决这个问题:

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

 对于内部需要转换的字符串使用tr标记的utf8进行转换,对于外部字符串不用utf8,使用本地字符集编码解码。

 以上是针对qt4的情况,在qt5中
TextCodec::setCodecForTr(...),QTextCodec::setCodecForCStrings(...)
这两个函数直接被取消了,这样一来,就没办法使用上面的代码解决乱码问题了,不过好在的是qt5中QString默认编码是utf8编码了,默认的utf8编码是支持中文的,所以直接就解决了编码乱码的根源问题,但如果万一qt5.0没有使用utf8,也可以使用如下代码转换成utf8:
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
 当然如果这种方法导致了无法调用中文路径程序的问题,就说明你系统本身采用的不是utf8编码,那么只能通过QString::from***,和Qtextcodec来解决了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值