Chapter1 (徹底解決Qt中文亂碼以及漢字編碼的問(wèn)題(UTF-8/GBK)
原文鏈接:
這篇文章有點(diǎn)長(zhǎng),內(nèi)容有點(diǎn)多,如果時(shí)間急迫,可以直接翻頁(yè)去末尾看結(jié)論。紅色字體加粗的。
一、Qt Creator環(huán)境設(shè)置
1、cpp或h文件從window上傳到Ubuntu后會(huì)顯示亂碼,原因是因?yàn)閡buntu環(huán)境設(shè)置默認(rèn)是utf-8,Windows默認(rèn)都是GBK.
我們使用的Windows系統(tǒng)本地字符集編碼為GBK。
2、Windows環(huán)境下,Qt Creator,菜單->工具->選項(xiàng)->文本編輯器->行為->文件編碼->默認(rèn)編碼,常用的選項(xiàng)有以下幾個(gè):
System(簡(jiǎn)體中文windows系統(tǒng)默認(rèn)指的是GBK編碼)
GBK/windows-936-2000/CP936/MS936/windows-936
UTF-8
二、編碼知識(shí)科普
Qt常見(jiàn)的兩種編碼是:UTF-8和GBK
★UTF-8:Unicode TransformationFormat-8bit,允許含BOM,但通常不含BOM。是用以解決國(guó)際上字符的一種多字節(jié)編碼,它對(duì)英文使用8位(即一個(gè)字節(jié)),中文使用24為(三個(gè)字節(jié))來(lái)編碼。UTF-8包含全世界所有國(guó)家需要用到的字符,是國(guó)際編碼,通用性強(qiáng)。UTF-8編碼的文字可以在各國(guó)支持UTF8字符集的瀏覽器上顯示。如果是UTF8編碼,則在外國(guó)人的英文IE上也能顯示中文,他們無(wú)需下載IE的中文語(yǔ)言支持包。
★GBK是國(guó)家標(biāo)準(zhǔn)GB2312基礎(chǔ)上擴(kuò)容后兼容GB2312的標(biāo)準(zhǔn)。GBK的文字編碼是用雙字節(jié)來(lái)表示的,即不論中、英文字符均使用雙字節(jié)來(lái)表示,為了區(qū)分中文,將其最高位都設(shè)定成1。GBK包含全部中文字符,是國(guó)家編碼,通用性比UTF8差,不過(guò)UTF8占用的數(shù)據(jù)庫(kù)比GBD大。GBK是GB2312的擴(kuò)展,除了兼容GB2312外,它還能顯示繁體中文,還有日文的假名。
★GBK、GB2312等與UTF8之間都必須通過(guò)Unicode編碼才能相互轉(zhuǎn)換:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
★在簡(jiǎn)體中文windows系統(tǒng)下,ANSI編碼代表GBK/GB2312編碼,ANSI通常使用0x800xFF范圍的2個(gè)字節(jié)來(lái)表示1個(gè)中文字符。0x000x7F之間的字符,依舊是1個(gè)字節(jié)代表1個(gè)字符。Unicode(UTF-16)編碼則所有字符都用2個(gè)字節(jié)表示。
三、編碼轉(zhuǎn)換
Windows自帶的記事本,無(wú)法查看UTF-8編碼的文件到底有無(wú)BOM,需要使用其他文件編輯器,比如EditPlus或者SublimeText。
UTF-8與ANSI(即GBK)的互轉(zhuǎn),可以使用EditPlus工具"文件另存為"或者Encodersoft編碼轉(zhuǎn)換工具對(duì).cpp和.h源文件文本進(jìn)行批量轉(zhuǎn)換.
四、QString顯示中文亂碼的原因
我們使用的Windows系統(tǒng)本地字符編碼(Local字符集)為GBK。編譯器分析出源文件字符編碼之后,會(huì)進(jìn)行解碼再編碼,將源字符集轉(zhuǎn)碼成執(zhí)行字符集。執(zhí)行字符集一般默認(rèn)為使用本地字符編碼(Local字符集)。
Qt5可以設(shè)置Local字符集,GBK/UTF-8
QTextCodec *codec = QTextCodec::codecForName("UTF-8");//或者"GBK",不分大小寫(xiě)
QTextCodec::setCodecForLocale(codec);
Qt5中QString內(nèi)部采用unicode字符集,utf-16編碼。構(gòu)造函數(shù)QString::QString(const char *str)默認(rèn)使用fromUtf8(),將str所指的執(zhí)行字符集從utf-8轉(zhuǎn)碼成utf-16。
由上面fromUtf8()可知,QString需要執(zhí)行字符集編碼為utf-8,然后以u(píng)tf-8進(jìn)行解碼,再編碼為utf-16才能獲得正確的字符編碼。顯示中文亂碼的原因其實(shí)就是QString轉(zhuǎn)碼方式與執(zhí)行字符集不一致。(比如,源字符集為本地字符集GBK編碼,QString以u(píng)tf-8的方式進(jìn)行解碼,會(huì)導(dǎo)致獲得錯(cuò)誤的二進(jìn)制編碼,再將錯(cuò)誤二進(jìn)制轉(zhuǎn)為utf-16就會(huì)出現(xiàn)亂碼。)
五、Qt編碼指定
Qt需要在main()函數(shù)指定使用的字符編碼:
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//設(shè)置中文字體
a.setFont(QFont("Microsoft Yahei", 9));
//設(shè)置中文編碼
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
QTextCodec *codec = QTextCodec::codecForName("GBK");
#else
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
#endif
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
#else
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec);
#endif
return a.exec();
}
這里只列舉大家最常用的3個(gè)編譯器(微軟VC++的cl編譯器,Mingw中的g++,Linux下的g++),源代碼分別采用GBK和無(wú)BOM的UTF-8以及有BOM的UTF-8這3種編碼進(jìn)行保存,發(fā)生的現(xiàn)象如下表所示。
情況1:指的是Local字符集為GBK
情況2:指的是Local字符集為UTF-8
如果您使用的是Visual C++編譯器,則默認(rèn)情況下不會(huì)將您的源代碼視為utf-8編碼。除非有BOM,否則它將使用您當(dāng)前的代碼頁(yè)進(jìn)行解釋。就是說(shuō),當(dāng)使用Visual C++編譯程序的時(shí)候,它會(huì)分析源文件采用何種編碼,有BOM標(biāo)識(shí)符則可以正確識(shí)別其編碼是UTF-8,若沒(méi)有BOM標(biāo)識(shí)符則認(rèn)為其使用本地字符集編碼(Local字符集)。Local字符集是什么?取決于你的設(shè)置QTextCodec *codec = QTextCodec::codecForName(???);
如果源文件是UTF-8+BOM的編碼方式,還需要在頭文件加入
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif
或者添加QMAKE_CXXFLAGS += /utf-8到您的.pro文件中。
如果源文件是UTF-8+無(wú)BOM的編碼方式,則一定不能加#pragma execution_character_set(“utf-8”),不然會(huì)產(chǎn)生亂碼。
六、測(cè)試案例
案例1、中文字符串測(cè)試
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif
#include <QApplication>
#include <QFont>
#include <QTextCodec>
#include <QPushButton>
#include <QDebug>
#include <QString>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//設(shè)置中文字體
a.setFont(QFont("Microsoft Yahei", 9));
//設(shè)置中文編碼
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
QTextCodec *codec = QTextCodec::codecForName("gbk");
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
#endif
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
QTextCodec::setCodecForLocale(codec);
#endif
QString str(QObject::tr("1中文"));
qDebug() << str;
qDebug() << QStringLiteral("2中文");
qDebug() << QString::fromLatin1("3中文");
qDebug() << QString::fromLocal8Bit("4中文");
qDebug() << QString::fromUtf8("5中文");
qDebug() << QString::fromWCharArray(L"6中文");
return a.exec();
}
當(dāng)QTextCodec::codecForName(“utf-8”);時(shí),
QString::fromLocal8Bit和QString::fromUtf8是等效的。
當(dāng)QTextCodec::codecForName(“gbk”);時(shí),
QString::fromLocal8Bit和QString::fromUtf8是不等效的。
案例2、QCom跨平臺(tái)串口調(diào)試助手(Qt開(kāi)源社區(qū)-致力于Qt普及工作! - qt qml linux 嵌入式 教程!)
源代碼qcom\mainwindow.cpp,aboutdialog.cpp等文件用的是UTF-8編碼(無(wú)BOM);但是qcom\qextserial*.*文件用的是ANSI編碼.在linux環(huán)境編譯完全OK.
筆者Windows環(huán)境的Qt Creator+微軟VC++編譯器,環(huán)境設(shè)置用的是ANSI(即GBK)編碼.編譯源文件會(huì)報(bào)錯(cuò).
錯(cuò)誤提示"fatal error C1018: 意外的 #elif".
解決方法由兩種:
方法1:
把qcom\的所有cpp和h文件都用工具轉(zhuǎn)換成ANSI編碼,main()函數(shù)使用QTextCodec::setCodecForTr(QTextCodec::codecForName(“GBK”));
方法2:
先把Qt Creator環(huán)境設(shè)置用的是UTF-8編碼,
再把qcom\的所有cpp和h文件都用工具轉(zhuǎn)換成UTF-8+BOM編碼,請(qǐng)注意,如果文件轉(zhuǎn)換成UTF-8(無(wú)BOM),編譯仍會(huì)失敗.main()函數(shù)使用QTextCodec::setCodecForTr(QTextCodec::codecForName(“GBK”));//注意,此處仍是"GBK",不是"UTF-8"
重新編譯,OK!
其它:
七、結(jié)論
Windows環(huán)境下,Qt Creator+微軟VC++編譯器,新建工程,
1、如果該工程不需要跨平臺(tái)使用(只在win),那么工程設(shè)置請(qǐng)使用GBK的編碼方式.
2、如果該工程要跨平臺(tái)使用(win+linux),那么工程設(shè)置請(qǐng)使用UTF-8+BOM的編碼方式.
另外,還需要在預(yù)編譯頭文件加入
CONFIG += c++11
#可以在項(xiàng)目中使用預(yù)編譯頭文件的支持
CONFIG += precompile_header
#預(yù)編譯頭文件路徑
PRECOMPILED_HEADER = $$PWD/stdafx.h
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
# pragma execution_character_set("utf-8")
#endif
或者添加QMAKE_CXXFLAGS += /utf-8到您的.pro文件中。
3、Linux環(huán)境下,Qt Creator+gcc,新建工程,
沒(méi)有GBK編碼可選,默認(rèn)是UTF-8(無(wú)BOM)編碼方式,考慮到跨平臺(tái),建議選擇UTF-8+BOM的編碼方式.
★★★★★★★★★★★★綜上所述,解決亂碼的方法概括如下:★★★★★★★★★★★★
1、如果IDE是Qt Creator,把它的環(huán)境設(shè)置為“UTF-8+BOM”編碼。
2、如果IDE是Visual Studio,請(qǐng)下載插件,名稱(chēng)是ForceUTF8 (with BOM),所有源文件和頭文件都會(huì)保存為“UTF-8+BOM”編碼。
3、如果編譯器是MSVC,請(qǐng)?jiān)陬A(yù)編譯頭stdafx.h文件加入
#if defined(_MSC_VER) && (_MSC_VER >= 1600)
pragma execution_character_set(“utf-8”)
#endif
4、源碼文件main函數(shù)入口設(shè)置中文編碼:
#include <QFont>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//設(shè)置中文字體
a.setFont(QFont("Microsoft Yahei", 9));
//設(shè)置中文編碼
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
QTextCodec *codec = QTextCodec::codecForName("gbk");
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
#endif
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
QTextCodec::setCodecForLocale(codec);
#endif
MainView w;
w.show();
return a.exec();
}
5、如此一來(lái),不管是MSVC編譯器還是MinGW編譯器,都能編譯通過(guò),且支持中文!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
Chapter2 Qt解決中文顯示亂碼問(wèn)題
https://blog.csdn.net/qq_45254369/article/details/125323917
將Text codec for tools 設(shè)置為utf-8 即可
設(shè)置文件默認(rèn)編碼
1、點(diǎn)擊左側(cè)文本編輯器。
2、 第二步,設(shè)置文件編碼。默認(rèn)編碼選擇utf-8, utf-8 bom 設(shè)置為 如果有編碼是utf-8則添加。
Chapter3 Qt解決中文亂碼問(wèn)題(更新于2023.10.1)
https://blog.csdn.net/qq_73725757/article/details/129645554
Chapter4 QString各種字符編碼轉(zhuǎn)化,適用不同Linux系統(tǒng)中文亂碼問(wèn)題
https://blog.csdn.net/qq_45613672/article/details/132457500
Chapter5 qt中文亂碼原因分析及解決方案
https://blog.csdn.net/u010810750/article/details/107774481
首先說(shuō)明幾個(gè)基礎(chǔ)概念
UTF-8 BOM 和 UTF-8。BOM在文件頭位置占三個(gè)字節(jié),用來(lái)標(biāo)識(shí)UTF-8編碼,軟件通過(guò)BOM來(lái)識(shí)別這個(gè)文件是否是UTF-8編碼。
源碼字符集。源碼文件使用某種編碼格式保存。
執(zhí)行字符集??蓤?zhí)行程序內(nèi)保存的編碼(程序執(zhí)行時(shí)內(nèi)存中字符串編碼)。
QString中統(tǒng)一采用utf-16(Unicode)存儲(chǔ)字符串。
QString::fromxxx()函數(shù)。代表將字符串以對(duì)應(yīng)格式去解析成Unicode,fromLocal8Bit()代表使用本地字符集(系統(tǒng)設(shè)置)轉(zhuǎn)換成Unicode;fromUtf8代表從utf-8轉(zhuǎn)換成Unicode。Qt程序運(yùn)行的時(shí)候字符串編碼在QString中實(shí)際都是以u(píng)nicode編碼存儲(chǔ)的,通過(guò)使用QString::fromxxx()轉(zhuǎn)換成轉(zhuǎn)換成unicode存到QString中。
亂碼產(chǎn)生的原因
中文處理的時(shí)候,編譯器首先解析源碼字符集,根據(jù)具體情況將源碼字符集解析為執(zhí)行字符集,再將執(zhí)行字符集轉(zhuǎn)換為QString的編碼(unicode)。QString的編碼是固定的,要想整個(gè)過(guò)程無(wú)亂碼,那么源碼字符集到執(zhí)行字符集的轉(zhuǎn)換必須確定。換句話說(shuō)就是編譯器必須明確文件的編碼和執(zhí)行字符集。這個(gè)不同的編譯器的邏輯是不一樣的。以MSVC和Mingw為例分析:
MSVC
源碼字符集:源文件有BOM的情況下按BOM解釋?zhuān)瑹o(wú)則使用本地Locale字符集(隨系統(tǒng)設(shè)置而變)。
執(zhí)行字符集:使用本地Locale字符集(隨系統(tǒng)設(shè)置而變)。
Mingw
源碼字符集和執(zhí)行字符集默認(rèn)都按utf-8解析。
因此亂碼的原因有:
編譯器解讀源碼字符集錯(cuò)誤,比如utf-8的源碼不帶bom編譯器會(huì)當(dāng)成locale,執(zhí)行字符集也是locale所以不需要轉(zhuǎn)換,但是實(shí)際utf-8的編碼到locale是需要轉(zhuǎn)換的。
源碼字符集到執(zhí)行字符集的轉(zhuǎn)換錯(cuò)誤。比如需要解析執(zhí)行字符集utf-8,需要使用fromUtf8。但是卻使用了其它的轉(zhuǎn)換方式fromXXX,這是使用了錯(cuò)誤的轉(zhuǎn)換算法。
字符解析錯(cuò)誤。比如程序中的字符串二進(jìn)制是utf-8的,設(shè)置執(zhí)行字符集是loacle,那么解析就會(huì)出錯(cuò)。
解決方案
最好的解決方案是將源碼保存成utf8 bom,執(zhí)行字符集也選為utf8
對(duì)于MSVC,源碼字符集之所以保存成 bom是因?yàn)橹挥衎om 編譯器才能識(shí)別出來(lái)源碼字符集,執(zhí)行字符集設(shè)置為utf8在C++98的MSVC上是沒(méi)有什么好辦法的,只能使用QString::fromUtf8設(shè)置轉(zhuǎn)換算法。c++ 11比較方便,提供了設(shè)置執(zhí)行字符集的方法 #pragma execution_character_set(“utf-8”)。
之所以說(shuō)這是最好的解決方案,是因?yàn)檫@種設(shè)置在qt5以上的版本中具有良好的跨平臺(tái)性,Mingw和GCC都支持這種方案。
采用這種方案無(wú)需再寫(xiě)QString::fromxxx()函數(shù)(此中情況下發(fā)現(xiàn)無(wú)論是在msvc還是mingw下,對(duì)于中文常量的處理加不加fromUtf8都能正常處理,分析了一部分源碼和注釋后猜測(cè)是因?yàn)閺腸onst char*到QString的隱式轉(zhuǎn)換內(nèi)部使用了QStringData保存字符串的空間,然后這個(gè)字符串 從 utf-8轉(zhuǎn)碼為unicode并拷貝到data)。
使用vs2010以上版本開(kāi)發(fā)程序的時(shí)候,可以安裝ForceUTF8(with BOM)插件,能夠使新創(chuàng)建的工程文件都是BOM格式。
#pragma execution_character_set(“utf-8”)不需要硬編碼到代碼中,可以使用inc文件在pri文件中設(shè)置編譯器和鏈接器flag參數(shù)即可
將#pragma execution_character_set(“utf-8”)保存在xxx.inc中
在pri中添加:
win32-msvc*:QMAKE_CXXFLAGS += -FI"$$PWD/xxx.inc"
win32-msvc*:QMAKE_CFLAGS += -FI"$$PWD/xxx.inc"
另外有一點(diǎn)需要注意,編譯器根據(jù)ui文件生成的ui_xxx.h文件默認(rèn)編碼是utf-8(無(wú)BOM),里面涉及到的漢字都已經(jīng)轉(zhuǎn)換成了字符編碼,所以u(píng)i文件生成的源碼無(wú)需特殊處理。
總結(jié)
Qt開(kāi)發(fā)環(huán)境統(tǒng)一設(shè)置(設(shè)置兩個(gè)地方:環(huán)境和文本剪輯器),默認(rèn)編碼選擇utf-8, utf-8 bom 設(shè)置為 如果有編碼是utf-8則添加。
在需要顯示中文的地方使用QStringLiteral宏處理一下。
ui->label_2->setText(QStringLiteral("這是UTF-8 BOM編碼的中文顯示"));
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-743485.html
QStringLiteral是一個(gè)宏,在支持lambda表達(dá)式的c++11中,直接解析源碼字符集到寬字節(jié)。不支持lambda的編譯環(huán)境中等同于fromUtf8,只要保證源碼字符集編譯器識(shí)別正確就不會(huì)出現(xiàn)亂碼,因?yàn)樗侵苯愚D(zhuǎn)換成了寬字符,和執(zhí)行字符集沒(méi)有關(guān)系(個(gè)人認(rèn)為)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-743485.html
到了這里,關(guān)于徹底解決Qt中文亂碼以及漢字編碼的問(wèn)題(UTF-8/GBK)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!