6.编码测试和总结一
/////////////////////////////////测试环境/////////////////////////////////////////////////
操作系统: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
使用编码函数或方式:无
测试结果:
总结:
从十六进制可以看出,文件编码采用带有BOM的utf-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())); }
不是很常用,也不是很好理解,这里先做一下记录吧,待用到时候仔细研究。