徹底解決QT編碼問題


徹底解決QT編碼問題

字符串常量、"中文"是傳統的char類型的窄字符串、在使用的時候只需要告訴QString這兩個漢字采用的編碼構造QString。

const char * str = "中文";
QString qstr = str;   //相當於調用QString::QString(const char * str)初始化一個QString

概念1:源文件是有編碼的
"中文" 在不同的編碼下對應不同的二進制形式
可能在GBK編碼下是:ce d2 ca c7
在Latin-1編碼下是:ba ba d7 d6

概念2:QString內部采用的是Unicode

一個問題,源代碼中假如有4個字節"\xce\xd2\xca\xc7“該怎么轉換成Unicode並存儲在QString內。按照GBK、BIG5、Latin-1還是其他方式...
在你不告訴它的情況下,它默認選擇了Latin-1,於是4個字符"ÎÒÊÇ"的unicode碼被存進了QString中。最終,4個Latin字符出現在你期盼看到2中文字符的地方,所謂的亂碼出現了

解決方式

問題很簡單,當你需要從窄字符串 char* 轉成Unicode的QString字符串的,你需要告訴QString你的這串char* 中究竟是什么編碼?GBK、BIG5、Latin-1
理想情況就是:將char* 傳給QString時,同時告訴QString自己的編碼是什么

就像下面的函數一樣,QString的成員函數知道按照何種編碼來處理 C 字符串
QString QString::fromAscii ( const char * str, int size = -1 )
QString QString::fromLatin1 ( const char * str, int size = -1 ) 
QString QString::fromLocal8Bit ( const char * str, int size = -1 )
QString QString::fromUtf8 ( const char * str, int size = -1 )
QString 只提供了這幾個成員函數,遠遠滿足不了大家的需求,比如,在簡體中文Windows下,local8Bit是GBK,可是有一個char串是 BIG5 或 Latin-2怎么辦?

可以使用強大的QTextCodec,首先QTextCodec肯定知道自己所負責的編碼的,當你把一個char串送給它,就能正確將其轉成Unicode
QString QTextCodec::toUnicode ( const char * chars ) const

可是這個調用太麻煩了
想直接
QString a= str;
QString a(str);

這樣一來肯定沒辦法同時告訴 QString 你的str是何種編碼了,只能通過其他方式了。
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
設置QString默認采用的編碼。而究竟采用哪一個,一般來說就是源代碼是GBK,就用GBK,源代碼是UTF-8就用UTF-8。但有一個例外,如果你保存成了帶BOM的UTF-8而且用的微軟的cl編譯器,此時仍是GBK。

總結

QString內部采用的是 Unicode,它可以同時存放GBK中的字符"我是漢字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"ÎÒÊǺº×Ö"。

當你需要從窄字符串 char* 轉成Unicode的QString字符串的,你需要告訴QString你的這串char* 中究竟是什么編碼?GBK、BIG5、Latin-1?

在你不告訴它的情況下,它默認選擇了Latin-1,於是8個字符"ÎÒÊǺº×Ö"的unicode碼被存進了QString中。最終,8個Latin字符出現在你期盼看到4中文字符的地方,

所謂的亂碼出現了。

網上有很多方法介紹直接在main.cpp里設置:

QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);

其實這在某些情況下也是有問題的,因為程序可能讀到系統的中文路徑,或者調用中文路徑下的外部程序,這時候如果系統是gb2312就有問題了。

因為中文路徑的編碼是采用utf-8存到QString里的,系統讀中文路徑解碼的時候采用的卻是系統的gb2312,所以會調不起帶中文路徑的外部程序。

以上問題下面方法可以解決:

QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForTr(codec);
QTextCodec::setCodecForLocale(QTextCodec::codecForLocale()); //設置GBK到本地
QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());

對於外部字符串編碼解碼全部采用本地編碼。

在QT5中,加上這句,源文件使用UTF-8編碼,不帶BOM
QApplication a(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM