QT乱码总结6.编码测试和总结一

QT乱码总结0.Qt乱码产生因素
https://blog.csdn.net/liujiayu2/article/details/103167953

QT乱码总结1.Unicode 和 UTF-8
https://blog.csdn.net/liujiayu2/article/details/103168020

QT乱码总结2.gbk和ANSI和gb2312的区别
https://blog.csdn.net/liujiayu2/article/details/103168168

QT乱码总结3.UNICODE有无BOM
https://blog.csdn.net/liujiayu2/article/details/103168236

QT乱码总结4.细谈本地编码
https://blog.csdn.net/liujiayu2/article/details/103168249

QT乱码总结5.万能解决方案
https://blog.csdn.net/liujiayu2/article/details/103168272

QT乱码总结6.编码测试和总结一
https://blog.csdn.net/liujiayu2/article/details/103168289

QT乱码总结7.编码测试和总结二
https://blog.csdn.net/liujiayu2/article/details/103168301

QT乱码总结8.编码测试和总结三
https://blog.csdn.net/liujiayu2/article/details/103168307

QT乱码总结9.编码测试和总结四
https://blog.csdn.net/liujiayu2/article/details/103168317

QT乱码总结编码测试工程:
https://download.csdn.net/download/liujiayu2/11987065

 

 

/测试环境/

操作系统:WIN7 简体中文版

编译器:VS2010 英文版

QT版本:Qt 4.8.6

/测试编码

我爱中国

 

ANSI(GBK)编码:CE D2 B0 AE D6 D0 B9 FA

 

UTF-8编码:E6 88 91 E7 88 B1 E4 B8 AD E5 9B BD

 

UTF-8编码(bom):EF BB BF E6 88 91 E7 88 B1 E4 B8 AD E5 9B BD

 

UNICODE编号:\u6211\u7231\u4e2d\u56fd

/

 

/测试代码/

//#pragma execution_character_set("AAAAA")

//#pragma execution_character_set("gb2312")

#pragma execution_character_set("utf-8")

//#pragma execution_character_set("big5")

 

Widget::Widget(QWidget *parent) :

    QWidget(parent),

    ui(new Ui::Widget)

{

    ui->setupUi(this);

 

    setWindowTitle("CodecStudy_Creator");

 

 

    QString str("我爱中国");

    ui->lineEdit->setText(str);

 

    std::string strStdString = str.toStdString();

    std::wstring strStdWString = str.toStdWString();

 

    QString hexShow;

    for (int i=0; i<strStdString.length(); i++)

    {

        unsigned char curChar= (unsigned char)strStdString.at(i) ;

 

        char buf[6]={0};

        sprintf(buf,"%02x ",curChar);

 

        hexShow += buf;

    }

    ui->lineEditHex->setText(hexShow);

 

    QString unicodeShow;

    QChar qcharArray[20]={0};

    for (int i=0;i<str.count();i++)

    {

        QChar qchar = str.at(i);

        qcharArray[i] = qchar;

 

        char buf[7]={0};

        const ushort shortChar = qchar.unicode();

        sprintf(buf,"\\u%04x ", shortChar);

 

        unicodeShow += buf;

    }

    ui->lineEditUnicode->setText(unicodeShow);

 

    int a = 0;

}/

 

/注意问题/

1.更改编码使用工具NodePad++,更改编码之后,可能需要重写中文字符

 

2.VS编辑器支持探测当前文件编码,但是不支持实时检测,只能在打开文件一瞬间你检测,

  所以当使用NodePad++更改文件编码的时候,推荐不要同时使用VS打开该文件。

 

3.QString内部采用的是UNICODE。默认编码是Latin-1(又名ISO-8859-1),Latin-1收录语言西欧语言,希腊语言,泰语,阿拉伯语,希伯来语(没有收录中文简体)。当字符转化为QString时候都要这样写:QString str = QString::fromXXX("***");

不能这样写:QString str = "***";除非设置了setCodecForString();

因为这样写默认是认为双引号内是Latin-1编码。至于为什么为什么默认是这种编码,可能因为这种编码特殊,使用了单字节内所有空间,其他编码都可以转化为这种编码,不过可能是乱码。

 

/

测试1:

文件编码:ANSI

使用编码函数或方式:无

测试结果:

总结:

从十六进制可以看出,字符串和文件编码一直都是采用的gbk编码。

/

测试2:

文件编码:UTF-8没有BOM

使用编码函数或方式:无

测试结果:

总结:

从十六进制可以看出,字符串和文件编码一直都是采用的utf-8编码。

/

测试3:

文件编码:UTF-8有BOM

使用编码函数或方式:无

测试结果:

总结:

从十六进制可以看出,文件编码采用带有BOMutf-8编码的时候,字符串进行编码的时候采用的是本地编码gbk而不是utf-8编码

/

测试4:

文件编码:Latin-1(又名ISO-8859-1)

使用编码函数或方式:无

测试结果:

改变文件编码为Latin-1之后我们就看到编辑器里面就出现了乱码,说明latin-1没有收录中文简体。

不过,我们还是运行一下看看结果。

为什么要进行这样一次测试?

理论上讲如果Latin-1有收录中文简体的话,我们不用进行其他乱七八造的设置,只要把文本的编码改为Latin-1即可达到中文正常显示的效果。

/

测试5:

查看各种编码的区别:

前四种方式的结果是一样的。

前四种方法 + ANSI文件(或者UNICODE带BOM) =  正确显示

第五种方法 + UNICODE不带BOM文件  =  正确显示

 

/

测试6:

使用编码函数或方式:QString::fromLocal8Bit

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

QString::fromLocal8Bit + ANSI文件(或者UNICODE带BOM) =  正确显示

QString::fromLocal8Bit + UNICODE不带BOM文件  =  乱码

原因分析:

这个很好理解,这个函数名字的意思是 从本地8位编码 到Unicode

中文简体WIndows操作系统本地编码是gb2312啊。这就很好理解上面的情况。

/

测试7:

使用编码函数或方式:QString:: fromUtf8

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

QString:: fromUtf8+ ANSI文件(或者UNICODE带BOM) =  乱码

QString:: fromUtf8+ UNICODE不带BOM文件  =  正确显示

原因分析:

这个很好理解,这个函数名字的意思是 从utf-8编码 到Unicode

/

测试8:

使用编码函数或方式:QString:: fromLatin

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

测试结果和什么都不写结果是一样一样的。

原因分析:

这个很好理解,我们之前就说过,QString默认是Latin-1编码

/

测试9:

使用编码函数或方式:QString:: fromAscii

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

测试结果令我们大跌眼镜,本以为应该同fromlocal8bit一样。都是从本地编码到UNICO嘛。

看了一下这个函数的注释我们就明白了。

         Note that, despite the name, this function actually uses the codec

    defined by QTextCodec::setCodecForCStrings() to convert \a str to

    Unicode. Depending on the codec, it may not accept valid US-ASCII (ANSI

    X3.4-1986) input. If no codec has been set, this function does the same

    as fromLatin1().

注释写的很明确,不要从函数名字猜测这个函数是干什么的。这个函数实际是和

QTextCodec::setCodecForCStrings()搭配使用的,在调用setCodecForCStrings之后,QString:: fromAscii

使用的就是setCodecForCStrings里面的编码。如果不对setCodecForCStrings进行设置,QString:: fromAscii就等同与QString:: fromLatin1。简而言之,蛋用没有。

/

测试10:

使用编码函数或方式:QObject::tr

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

这个函数是和QTextCodec::setCodecForTr联合使用的,单单使用一个是没有效果的。直接使QObject::tr和只是送tr效果是一样的。

/

测试11:

使用编码函数或方式:QObject:: trUtf8

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

效果等同与QString::fromUtf8()

/

测试12:

使用编码函数或方式:#pragma execution_character_set("utf-8")

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

使用与不使用完全没啥区别。这预示着,要不本身就是默认这种方式,要不就是这种设置压根没起到作用,为此,我们进行了测试13

/

测试12:

使用编码函数或方式:

QString::fromUtf8 (目的是保证在文件unicode无bom情况下正确显示中文字符)

#pragma execution_character_set("utf-8")

#pragma execution_character_set("gb2312")

#pragma execution_character_set("Latin-1")

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

QString::fromUtf8 固定加上,3个pragma轮流上阵,3中文件编码轮流上阵。共9次测试结果,得到如下结论,#pragma execution_character_set 在本测试环境下是起不到任何作用的。

 

/

测试13:

使用编码函数或方式:QString::fromStdString

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

加与不加没有区别。

我们看一下Qt源码:

inline QString QString::fromStdString(const std::string &s)

{ return fromAscii(s.data(), int(s.size())); }

结合我们之前对fromAscii这个函数总结这个现象就很好理解了。

 

/

测试14:

使用编码函数或方式:QString::fromStdWString

文件编码:ANSI、UNICODE无BOM、UNICODE有BOM

测试结果:

QString str(QString::fromStdWString("我爱中国"));这样写编译不过。

 

给他加个L,编译过了,以前一直以为L这个东西是MFC的一个宏。开来C++也支持。

QString str(QString::fromStdWString(L"我爱中国"));

UNICODE无BOM下乱码,如下图:

ANSI和UNICODE有BOM下正常显示。

 

我们也看下qt源码

inline QString QString::fromStdWString(const QStdWString &s)

{ return fromWCharArray(s.data(), int(s.size())); }

不是很常用,也不是很好理解,这里先做一下记录吧,待用到时候仔细研究。

 

猜你喜欢

转载自blog.csdn.net/liujiayu2/article/details/103168289