一、产生乱码的根源:
有两种情况:
- 字符串存储时的编码和读取时的编码不同 (存是指字符以二进制形式存放在内存中,读是指将二进制数据转成字符串)
- 字符不在当前采用的编码表中(比如中文字符在ASCII没有对应)
二、QString采用什么编码
阅读QT官方文档,上面写的非常清楚:QString将字符存为16位的Unicode码(Unicode只是编码表)当以const char*来构建QString时,QString会调用fromAscii方法来将字符串转换成Unicode码,默认以Latin-1(ISO8859-1)来进行转换,通过QTextCodec::setCodecForCStrings()方法可以设置fromAscii使用的编码。也就是说简单的一个赋值语句:QString = "你好,世界";事实上已经进行了一次编码转换,默认从ISO8859-1转成Unicode码。这也就解释了为什么直接将中文赋值给QString会乱码。
三、如何进行编码转换
既然QString都是使用Unicode码进行保存,那么我们只要明确两件事就可以应付编码问题:
- 字符串存到QString中以什么编码转换到Unicode码
- QString中保存的字符串想要以什么编码进行输出(转换后应该以QByteArray返回),即从Unicode码转换成什么编码
QTextCodec在QT中负责编码的转换,它预定义了多种编码供我们使用,基本的使用方式如下:
QTextCodec* strCode = QTextCodec::codecForCStrings();
QTextCodec* GBK = QTextCodec::codecForName("GBK");
QString str1 = "你好世界";
QString u_str = strCode ->toUnicode(str1);
QString g_str = GBK->fromUnicode(u_str);
QTextCodec::codecForName("GBK")用来获取一个定义好的编码(查找官方文档),常用的方法有两个:fromUnicode(),从Unicode编码转换到你定义的编码,toUnicode(),从你定义的编码转换到Unicode编码。注意:转换后的结果实际上是QByteArray,QString有一个构造器接受QByteArray,如果将转换结果赋值给QString又要发生一次编码转换(调用fromAscii),所以即使转码完成QString输出还是可能会乱码,这时就要调用QTextCodec::setCodecForCStrings()来将QString使用的默认编码设置成我们想要的编码。但是如果是想输出文本的话,使用QByteArray会更加方便。
四、注意事项
实际应用中很可能出现QTextCodec* GBK = QTextCodec::codecForName("GBK");返回值为空的情况,这是因为QT需要手动加载中文编码插件。在QT的安装路径下找到plugins\codecs,将下面的qcncodecsd4.dll和qcncodecs4.dll拷贝到项目路径下的plugins\codecs下面,并在代码中添加到项目的libPath(注意路径只需要指定到plugin不需要指定到codecs哦)
QString pluginPath = QApplication::applicationDirPath()+"/plugin/";
QApplication::addLibraryPath(pluginPath);