日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

彻底弄懂Qt的编码(汉字乱码问题及相关函数作用)

發布時間:2023/12/10 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 彻底弄懂Qt的编码(汉字乱码问题及相关函数作用) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

測試1

新建test工程用于測試,main.c文件內容如下:

#include <QCoreApplication> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QString str_hanzi("百度"); // 漢字QString str_ascii("baidu.com"); // 字母qDebug() << str_hanzi;qDebug() << str_ascii;return a.exec(); }

運行, 輸出結果如下:

不出意料的亂碼。

下面開始分析。

此時,源代碼main.c的編碼是UTF-8 BOM。

使用Notepad++查看,編碼也是UTF-8 BOM。說明的確是UTF-8編碼。

查看目標文件main.obj,目標文件路徑如下:

使用Notepad++打開,搜索"百度"二字,結果如下:

同時可以看到此時Notepad++顯示文件內容使用的編碼是ANSI,即本地編碼,可以正確的顯示漢字。那就說明,編譯生成*.obj目標文件時,編譯器將源碼中的字符串由UTF-8 BOM轉換成了本地編碼。

接下來查看test.exe的內容,同樣搜索"百度"二字,如下圖:

和理論一樣,因為.exe文件就是.obj文件鏈接起來生成的。

到此為止,我們可以看到,源碼中的漢字字符串在生成可執行文件的過程中被轉換成了本地編碼。

那么和亂碼有什么關系呢?
我們知道,Qt內部是使用Unicode編碼的,即QString保存的是Unicode編碼的字符串。所有使用QString的函數都認為QString內部是Unicode字符串。
那么,當test.exe執行時,會讀取"百度"字符串,并使用QString::fromLatin1將字符串轉換為QString,拉丁文即英文,很顯然轉換中文會亂碼。通過修改QTextCodec::setCodecForLocale(codec);可以修改這個默認的轉換函數,將目標字符串視為指定編碼的字符串,再轉換為QString。

那么,那些QTextCodec類以及QString::fromLocal8bit的作用和原理是什么呢?

先說QSring::fromLocal8bit吧,這個比較簡單,意思就是從一個本地編碼的字符串生成一個QString字符串(Unicode),這樣的話,將該字符串傳遞給其他函數,就不會出現亂碼了。實驗之,首先修改程序如下:

#include <QCoreApplication> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QString str_hanzi("百度"); // 漢字QString str_ascii("baidu.com"); // 字母qDebug() << QString::fromLocal8Bit("百度"); // 修改了此處qDebug() << str_ascii;return a.exec(); }

輸出結果:

可以看到它實現了漢字的正常的顯示,和理論相同。

那么QTextCodec這個類是做什么的呢?
顧名思義,它的中文名應該是"文本編碼轉換器"(Text coding converter)或者"文本編解碼"(Text code decode),下面是網上流傳的一段代碼:

QTextCodec *codec = QTextCodec::codecForName("GBK"); QTextCodec::setCodecForTr(codec); QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForCStrings(codec);

下面修改程序:

#include <QCoreApplication>#include <QDebug> #include <QTextCodec> #include <QFile> int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QTextCodec *codec = QTextCodec::codecForName("GBK");QTextCodec::setCodecForTr(codec);QString str_hanzi("百度"); // 漢字QString str_ascii("baidu.com"); // 字母qDebug() << QString::fromLocal8Bit("百度");qDebug() << str_ascii;qDebug() << QObject::tr("百度");return a.exec(); }

輸出結果:

可以看到,這種方法也能實現正確顯示漢字。
但是這種方法的原理是什么?
關鍵在于QObject::tr()函數。它是翻譯函數(translate),同時會進行編碼轉換。它的默認行為是認為傳入的參數是Unicode編碼,不需要轉換。當你在程序中添加了設置tr編碼格式的代碼(如上面的程序,設置為GBK)時,會導致編碼從你指定的編碼(GBK)轉換成Unicode。如果把上面的程序中的GBK改成UTF-8,則會亂碼,因為該字符串的真正編碼是本地編碼GBK。實驗結果如下圖:

同理,如果將本地編碼設置成其他編碼,修改代碼如下

#include <QCoreApplication> #include <QDebug> #include <QTextCodec>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QTextCodec *codec = QTextCodec::codecForName("UTF-8");QTextCodec::setCodecForLocale(codec);QString str_hanzi("百度"); // 漢字QString str_ascii("baidu.com"); // 字母qDebug() << QString::fromLocal8Bit("百度");qDebug() << str_ascii;qDebug() << QObject::tr("百度");return a.exec(); }

這樣的話,使用QString::fromLocal8bit的轉換就會不正確,結果如下圖:

出乎意料的是,tr的轉換也出錯了。將UTF-8改回GBK,tr也還是亂碼:

于是添加一行QTextCodec::setCodecForTr(codec);,則顯示正確。它們之間會相互影響,這是我們沒有預料到的,不過還好這不是什么大問題,可以通過顯式設置來糾正。

結論

說了那么多,總結如下:
1、exe中的字符串編碼始終是本地編碼,與源代碼文件的編碼無關。
2、Qt內部需要使用Unicode編碼的字符串才能正確處理(顯示等操作)。
3、由于二者不同,所以對于漢字來說,必須經過轉換,第一是通過QString::fromLocal8bit函數來轉換,第二是通過QTextCodec來轉換。但是setTextCodecForTr、setTextCodecForLocale在高版本已被移除。

注意:
上述測試使用的是Qt4.8.5 msvc2010的版本。minGW還未測試,如果能直接在生成exe文件時直接生成Unicode字符串,那就不需要轉換了。

另外還有一種防止亂碼的方法,此種方法也可以解決國際化問題導致的亂碼,就是使用翻譯文件。在源碼中統一使用英文。在翻譯文件中實現不同版本的語言。

不得不提最后一種比較高級的方法:QStringLiteral宏。它可以直接生成Unicode字符串保存在可執行文件中的只讀區域。這樣運行時不會發生任何轉換。可以顯著提高程序運行效率。
測試代碼如下:

#include <QCoreApplication> #include <QDebug>int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);QString str_ascii("baidu.com"); // 字母qDebug() << QStringLiteral("a百度a");qDebug() << str_ascii;return a.exec(); }

生成的可執行文件再也找不到"百度"二字了。

Qt幫助文檔中說,QStringLiteral需要編譯器支持,如支持C++11就具有這種特性。Qt高版本一般也支持。具體性能方面的影響請看Qt的幫助文檔。


本文原創首發于公眾號Qt未來工程師,點此查看原文,轉載請注明出處。

總結

以上是生活随笔為你收集整理的彻底弄懂Qt的编码(汉字乱码问题及相关函数作用)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。