天天看點

徹底解決Qt中文亂碼以及漢字編碼的問題(UTF-8/GBK)(一)

尊重作者,支援原創,如需轉載,請附上原位址: https://blog.csdn.net/libaineu2004/article/details/19245205 這篇文章有點長,内容有點多,如果時間急迫,可以直接翻頁去末尾看結論。紅色字型加粗的。(#^.^#)

一、Qt Creator環境設定

1、cpp或h檔案從window上傳到Ubuntu後會顯示亂碼,原因是因為ubuntu環境設定預設是utf-8,Windows預設都是GBK.

我們使用的Windows系統本地字元集編碼為GBK。

2、Windows環境下,Qt Creator,菜單->工具->選項->文本編輯器->行為->檔案編碼->預設編碼,常用的選項有以下幾個:

System(簡體中文windows系統預設指的是GBK編碼)

GBK/windows-936-2000/CP936/MS936/windows-936

UTF-8

二、編碼知識科普

Qt常見的兩種編碼是:UTF-8和GBK

★UTF-8:Unicode TransformationFormat-8bit,允許含BOM,但通常不含BOM。是用以解決國際上字元的一種多位元組編碼,它對英文使用8位(即一個位元組),中文使用24為(三個位元組)來編碼。UTF-8包含全世界所有國家需要用到的字元,是國際編碼,通用性強。UTF-8編碼的文字可以在各國支援UTF8字元集的浏覽器上顯示。如果是UTF8編碼,則在外國人的英文IE上也能顯示中文,他們無需下載下傳IE的中文語言支援包。

★GBK是國家标準GB2312基礎上擴容後相容GB2312的标準。GBK的文字編碼是用雙位元組來表示的,即不論中、英文字元均使用雙位元組來表示,為了區分中文,将其最高位都設定成1。GBK包含全部中文字元,是國家編碼,通用性比UTF8差,不過UTF8占用的資料庫比GBD大。GBK是GB2312的擴充,除了相容GB2312外,它還能顯示繁體中文,還有日文的假名。

★GBK、GB2312等與UTF8之間都必須通過Unicode編碼才能互相轉換:

GBK、GB2312--Unicode--UTF8

UTF8--Unicode--GBK、GB2312

★在簡體中文windows系統下,ANSI編碼代表GBK/GB2312編碼,ANSI通常使用0x80~0xFF範圍的2個位元組來表示1個中文字元。0x00~0x7F之間的字元,依舊是1個位元組代表1個字元。Unicode(UTF-16)編碼則所有字元都用2個位元組表示。

三、編碼轉換

Windows自帶的記事本,無法檢視UTF-8編碼的檔案到底有無BOM,需要使用其他檔案編輯器,比如EditPlus或者SublimeText。

UTF-8與ANSI(即GBK)的互轉,可以使用EditPlus工具"檔案另存為"或者Encodersoft編碼轉換工具對.cpp和.h源檔案文本進行批量轉換.

四、QString顯示中文亂碼的原因

我們使用的Windows系統本地字元編碼(Local字元集)為GBK。編譯器分析出源檔案字元編碼之後,會進行解碼再編碼,将源字元集轉碼成執行字元集。執行字元集一般預設為使用本地字元編碼(Local字元集)。

Qt5可以設定Local字元集,GBK/UTF-8

QTextCodec *codec = QTextCodec::codecForName("UTF-8");//或者"GBK",不分大小寫

QTextCodec::setCodecForLocale(codec);

Qt5中QString内部采用unicode字元集,utf-16編碼。構造函數QString::QString(const char *str)預設使用fromUtf8(),将str所指的執行字元集從utf-8轉碼成utf-16。

由上面fromUtf8()可知,QString需要執行字元集編碼為utf-8,然後以utf-8進行解碼,再編碼為utf-16才能獲得正确的字元編碼。顯示中文亂碼的原因其實就是QString轉碼方式與執行字元集不一緻。(比如,源字元集為本地字元集GBK編碼,QString以utf-8的方式進行解碼,會導緻獲得錯誤的二進制編碼,再将錯誤二進制轉為utf-16就會出現亂碼。)

五、Qt編碼指定

Qt需要在main()函數指定使用的字元編碼:

#include <QTextCodec>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //設定中文字型  
    a.setFont(QFont("Microsoft Yahei", 9));
    //設定中文編碼
#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個編譯器(微軟VC++的cl編譯器,Mingw中的g++,Linux下的g++),源代碼分别采用GBK和無BOM的UTF-8以及有BOM的UTF-8這3種編碼進行儲存,發生的現象如下表所示。

情況1:指的是Local字元集為GBK

情況2:指的是Local字元集為UTF-8

源代碼的編碼

編譯器

顯示正常

顯示亂碼

GBK

win vs cl

情況1

情況2

win mingw-g++

linux g++

UTF-8(無BOM)

編譯失敗

error C2001: 常量中有換行符

UTF-8(有BOM)

情況2(有#pragma預處理)

情況2(沒有#pragma預處理)

如果您使用的是Visual C++編譯器,則預設情況下不會将您的源代碼視為utf-8編碼。除非有BOM,否則它将使用您目前的代碼頁進行解釋。就是說,當使用Visual C++編譯程式的時候,它會分析源檔案采用何種編碼,有BOM辨別符則可以正确識别其編碼是UTF-8,若沒有BOM辨別符則認為其使用本地字元集編碼(Local字元集)。Local字元集是什麼?取決于你的設定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+無BOM的編碼方式,則一定不能加#pragma execution_character_set(“utf-8”),不然會産生亂碼。