VC2010下Qt5的中文亂碼問題

要搞清楚這個問題,先要弄明白編碼。但是編碼問題實在太復雜,這里肯定講不開。

我先找一個例子,比如:“中文” 的 Unicode 碼點/UTF8編碼/GBK 分別是多少。

先去這個網站,輸入 “中文” 查詢對應的 Unicode 碼點/UTF8編碼:?
http://www.mytju.com/classcode/tools/encode_utf8.asp

Unicode的碼點分別是(十進制):中(20013),文(25991)。?
對應的UTF8編碼分別(16進制): 中(E4B8AD),文(E69687)。

然后再去下面這個網站,輸入 “中文” 查詢對應的 GBK 編碼:?
http://www.mytju.com/classcode/tools/encode_gb2312.asp

GBK編碼16進制(GBK內碼)分別是:中(D6D0),文(CEC4)。

現在已經知道了"中文"的UTF8和GBK編碼的具體值。?
我們再看看VC2010是怎么處理的。

1. 先看 無 BOM 的 UTF8 編碼的代碼 (utf8_no_bom.cpp)

01// utf8 no bom
02// 文件中包含不能在當前代碼頁(936)中表示的字符
03#include <stdio.h>
04?
05int?main() {
06????const?char* str =?"中文";
07????for(int?i =?0; i < sizeof(str); ++i) {
08????????printf("0x%x ", str[i]&0xFF);
09????}
10????return?0;
11????// Output:
12????// 0xe4 0xb8 0xad 0xe6
13}

輸出是:0xe4 0xb8 0xad 0xe6。?
感覺好像是對的。

但是,先別急:VC編譯時輸出了一條警告信息:?
utf8_no_bom.cpp : warning C4819: 該文件包含不能在當前代碼頁(936)中表示的字符。?
請將該文件保存為 Unicode 格式以防止數據丟失。

潛臺詞就是,你這個代碼有GBK不能表示的字符,請用Unicode方式保存。?
VC根本就沒把 代碼(utf8_no_bom.cpp) 當作UTF8,VC只是把它作為GBK處理罷了。

那為什么又輸出了正確的結果呢?

因為 VC 把 (utf8_no_bom.cpp) 當作 GBK,而編譯時也要轉換為本地編碼(也是GBK)。?
因此,UTF8編碼的 “中文”,被VC當作編碼為 “0xe4 0xb8 0xad 0xe6” 的其他中文處理了。?
VC已經不知道 “0xe4 0xb8 0xad 0xe6” 是對應 “中文” 字面值了。

但是在GBK(實際是無BOM的UTF8)轉GBK的過程中,發現了一些UTF8編碼的字符并不是?
GBK能表達的合理方式,因此就出現了那個C4819編譯警告。

2. 再看帶BOM的UTF8是怎么處理的 (utf8_with_bom.cpp)

01// utf8 with bom
02#include <stdio.h>
03?
04int?main() {
05????const?char* str =?"中文";
06????for(int?i =?0; i < sizeof(str); ++i) {
07????????printf("0x%x ", str[i]&0xFF);
08????}
09????return?0;
10????// Output:
11????// 0xd6 0xd0 0xce 0xc4
12}

編譯沒有警告,但是輸出有問題:0xd6 0xd0 0xce 0xc4。

源文件明明是 UTF8 編碼的格式"0xe4 0xb8 0xad 0xe6”,?
怎么變成了 “0xd6 0xd0 0xce 0xc4” (這個是GBK編碼)?

這就是VC私下干的好事:它自作聰明的將UTF8源代碼轉換為GBK處理了!

VC為何要做這樣蠢事?

原因是為了兼容老的VC版本。?
因為以前的VC不能處理UTF8,都是用本地編碼處理的。

3. 在看看真的GBK是怎么處理的 (gbk.cpp)

01// gbk
02#include <stdio.h>
03?
04int?main() {
05????const?char* str =?"中文";
06????for(int?i =?0; i < sizeof(str); ++i) {
07????????printf("0x%x ", str[i]&0xFF);
08????}
09????return?0;
10????// Output:
11????// 0xd6 0xd0 0xce 0xc4
12}

沒有編譯錯誤,輸出也和源代碼一致:“0xd6 0xd0 0xce 0xc4”。

因為源文件就是GBK,cl在編譯時GBK轉化為GBK,沒有改變字符串。

只是,現在很多人不想用GBK了(因為只能在中國地區用,不能表示全球字符)。

到這里,可以初步小結一下:

  1. VC編輯器和VC編譯器是2個概念,VC編輯器支持UTF8并不能表示VC編譯器也支持UTF8
  2. VC編輯器從2008?開始支持帶BOM的UTF8(不帶BOM的暫時沒戲,因為會本地編碼沖突)
  3. VC編譯器從2010開始重要可以支持UTF8了(雖然支持方式很不優雅)

4. 看看VC2010是怎么處理帶BOM的UTF8的 (utf8_with_bom_2010.cpp)

VC2010重要增加了UTF8的編譯支持(#pragma execution_character_set("utf-8")),?
具體查看:

http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/2f328917-4e99-40be-adfa-35cc17c9cdec

01// utf8 with bom (VC2010), 這句是重點!
02#pragma execution_character_set("utf-8")
03?
04#include <stdio.h>
05?
06int?main() {
07????const?char* str =?"中文";
08????for(int?i =?0; i < sizeof(str); ++i) {
09????????printf("0x%x ", str[i]&0xFF);
10????}
11????return?0;
12????// Output:
13????// 0xe4 0xb8 0xad 0xe6
14}

沒有編譯錯誤,輸出也和源代碼一致:“0xe4 0xb8 0xad 0xe6”。

UTF8編碼,UTF8輸出。完美!

回到 Qt5 的中文輸出問題。

Qt默認支持 VS2010/MinGW/Gcc 等編譯器,而它們現在都已經真正支持UTF8了。

當然,VS2010 對UTF8的支持會入侵代碼(#pragma execution_character_set("utf-8"))。

看看Qt官方論壇別人是怎么說的:?
http://qt-project.org/forums/viewthread/17617

Nothing special need to do, it will works by default.?
If the exec-charset of your your compiler is UTF-8.

簡單的說,從Qt5開始,源代碼就是默認UTF8編碼的。

當然,VC2010編輯器對帶BOM的UTF8也是認識,只可惜VC2010編譯器根本承認它是UTF8!

在繼續看官方論壇的回復:

You can write a simple example like this

01#include <QApplication>
02??#include <QLabel>
03?
04??#if?_MSC_VER >=?1600
05??#pragma execution_character_set("utf-8")
06??#endif
07?
08??int?main(int?argc,?char?*argv[])
09??{
10??????QApplication a(argc, argv);
11??????QLabel label("???ó??ń??");
12??????label.show();
13?
14??????return?a.exec();
15??}

If other people can reproduce your problem, you can file a bug.

教完整的解決方案(增加了Qt4/Qt5和非VC環境的判斷):

01// Coding: UTF-8(BOM)
02#if?defined(_MSC_VER) && (_MSC_VER >=?1600)
03# pragma execution_character_set("utf-8")
04#endif
05?
06#include <QApplication>
07#include <QTextCodec>
08#include <QLabel>
09?
10int?main(int?argc,?char* argv[])
11{
12????QApplication app(argc, argv);
13?
14#if?QT_VERSION < QT_VERSION_CHECK(5,0,0)
15#if?defined(_MSC_VER) && (_MSC_VER <?1600)
16????QTextCodec::setCodecForTr(QTextCodec::codecForName("GB18030-0"));
17#else
18????QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
19#endif
20#endif
21?
22????QLabel *label =?new?QLabel(QObject::tr("你好!"));
23????label->show();
24?
25????return?app.exec();
26}

有以下幾種類型(源代碼必須是帶BOM的UTF8):

  • Qt5+/VC2010+: 包含了?# pragma execution_character_set("utf-8")?已經支持中文
  • Qt5/VC2008-: 這個暫時誤解(我還沒找到方法)
  • Qt4+/VC2008-: 采用以前老的方式, 指定代碼為 “GB18030-0” 編碼
  • Qt4/Qt5/Linux: 只要是默認的UTF8環境, 應該都沒問題

其實這個問題不是Qt特有的, 追根溯源還是C/C++和編譯器的問題.

即使是支持UTF16的Java也同樣難逃此問題.

不過還好,?Go語言?算是徹底了解決了這個問題.?
以后轉向?Go語言?了 !

?

轉自開源中國?http://my.oschina.net/chai2010/blog/119833

我在電腦上找了一個顯示中文.ttf文件加到了QtSDk->Simulator->Application->fonts中就可以解決了

轉載于:https://www.cnblogs.com/Bonker/p/3453862.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259089.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259089.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259089.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Tomcat 的 DefaultServlet

問題描述&#xff1a; 群里有人測試 Spring MVC&#xff0c;沒有配置任何Controller&#xff0c;只配置了一個view resolver&#xff0c;指定了前綴后綴。 然后&#xff0c;他問的是 當訪問 localhost:8080/test 的時候&#xff0c;為什么會被重定向到 localhost:8080/test/ &a…

Python學習(七)面向對象 ——封裝

Python 類的封裝 承接上一節&#xff0c;學了Student類的定義及實例化&#xff0c;每個實例都擁有各自的name和score。現在若需要打印一個學生的成績&#xff0c;可定義函數 print_score() 該函數為類外的函數&#xff0c;如下&#xff1a; 1 class Student(object):2 def …

spss練習數據_SPSS篇——如何在成千上百萬個數據中標識重復個案

本文就帶大家來學習一個小技巧&#xff0c;如何運用SPSS標識重復個案。我們都知道在Excel中&#xff0c;通常會用到“篩選”功能來選出指定條件相同的單元格。那么在SPSS中&#xff0c;如何在成千上百萬個數據中篩選出重復的個案呢&#xff1f; 小編就是要告訴你&#xff0c;幾…

DOxygen for C++使用說明——Markdown支持

自Doxygen 版本1.8.0&#xff0c;Markdown被引進。 接下來&#xff0c;我們將先簡單介紹標準的Markdown語法&#xff0c;讀者可以進入Markdown官網查詢更詳細的細節。然后討論一下Doxygen支持的Markdown擴展&#xff0c;最后討論一下Doxygen對Markdown標準的實現細節。 Stand…

方程式漏洞之復現window2008/win7 遠程命令執行漏洞

前幾天就想寫的&#xff0c;因為一些緣故就沒寫。此次是在外網環境下進行的。大家在內網中也一個樣。 方法&#xff1a; 使用Eternalblue模塊&#xff0c;劍測是否有漏洞然后msf生成一個dll直接反彈shell. PS&#xff1a;win版本的不知道緣何生成出來的dll是0kb 我就在自己本地…

C++空類和string類

1. 空類 1.1 空類默認哪六個成員函數。 1 class Empty2 {3 public:4 Empty(); //缺省構造函數 Empty e;5 Empty( const Empty& ); //拷貝構造函數 Empty e2(e1);6 ~Empty(); //析構函數7 Empty& operator( const Empty& ); //賦值運算符…

客服會話 小程序 如何發起_小程序、公眾號、App三者如何融合布局?這里有一份避坑指南...

對產品經理來說&#xff0c;小程序無疑是2020年最火爆的詞之一了。我們能看到&#xff0c;就在今年疫情期間&#xff0c;小程序DAU達到4.5億&#xff0c;而超市、生鮮果蔬、社區購物等都同比增長100個點左右&#xff0c;小程序的商業價值很明顯地在快速釋放。小程序如此火爆&am…

DOxygen for C++使用說明——注釋代碼二

這一次我在谷歌搜索中檢索到了Doxygen在github的倉庫&#xff0c;進去一看&#xff0c;令人大喜&#xff0c;github倉庫里含有了一個Doxygen的官方配置文件Doxyfile,于是下載下來&#xff0c;發現Doxyfile已經配置了將倉庫中的\src文件編譯成Documentation,并且將結果放在了dox…

python super()(轉載)

一、問題的發現與提出 在Python類的方法&#xff08;method&#xff09;中&#xff0c;要調用父類的某個方法&#xff0c;在Python 2.2以前&#xff0c;通常的寫法如代碼段1&#xff1a; 代碼段1&#xff1a; class A:def __init__(self):print "enter A"print "…

Swagger+Spring mvc生成Restful接口文檔

2019獨角獸企業重金招聘Python工程師標準>>> Swagger 是一個規范和完整的框架&#xff0c;用于生成、描述、調用和可視化 RESTful 風格的 Web 服務。總體目標是使客戶端和文件系統作為服務器以同樣的速度來更新。文件的方法&#xff0c;參數和模型緊密集成到服務器端…

JavaScript——變量與基本數據類型

前言 JavaScript中的變量為松散類型&#xff0c;所謂松散類型就是指當一個變量被申明出來就可以保存任意類型的值&#xff0c;就是不像SQL一樣申明某個鍵值為int就只能保存整型數值&#xff0c;申明varchar只能保存字符串。一個變量所保存值的類型也可以改變&#xff0c;這在Ja…

vscode可以打開jupyternotebook嗎_剛剛,官方宣布 VS Code 支持 Python 全開發了!

關注Python高校每天早上23:10準時推送北京時間 2019 年 9 月 21 日&#xff0c;PyCon China 2019 在上海舉行。在下午的演講中&#xff0c;來自微軟開發工具事業部的資深研發工程師韓駿做了主題為《Python 與 Visual Studio Code 在人工智能應用中的最佳 Azure 實踐》的演講。在…

C++類的內聯成員函數應放在哪

今天復習C Primer的時候&#xff0c;看到了關于C類的內聯成員函數的放置&#xff0c;應該放在頭文件中。那么這到底是為什么 呢&#xff1f;僅僅是一種代碼規范問題還是必須這樣做呢&#xff1f; 下面我就來講講我自己的理解吧。要徹底理解這個問題&#xff0c;首先就要了解下函…

python selenium自動化(三)Chrome Webdriver的兼容

當一個自動化測試被實現在一個瀏覽器之后&#xff0c;我們會希望我們的測試能夠覆蓋到盡量多的別的瀏覽器。通過跨平臺的測試來保證我們的程序在多個瀏覽器下都能正常工作。 在安裝了selenium之后&#xff0c;firefox webdriver和IE webdriver就已經是ready to use的了&#xf…

NDK 編譯armebai-v7a的非4字節對齊crash Fatal signal 7 (SIGSEGV) 錯誤解決

一直都是編譯armabi的。沒有不論什么問題&#xff0c;這個架構是軟件模擬浮點運算的。后來看到NDK文檔上說armabi-v7a是針對有硬件處理浮點計算的arm cpu的。 于是就改動配置編譯armebai-v7a的so文件。 結果是編譯沒問題。一執行就是crash掉&#xff0c;Fatal signal 7 (SIGSEG…

作業三

作業三 第一章問題&#xff1a;書上寫的“Bug的多少可以直接衡量一個軟件的開發效率、用戶滿意度、可靠性和可維護性”&#xff0c;那么一個比較完好的軟件中一般大概會出現多少Bug? 第二章問題&#xff1a;現在開始訓練寫更多的程序能否更早地達到軟件工程師的標準&#xff1…

springboot默認數據源如何設置連接數_Spring Boot系列之配置數據庫連接池

在實際的應用開發中&#xff0c;與數據庫交互通常使用數據庫連接池來重用Connection對象&#xff0c;減少資源消耗。Spring Boot 的數據源是自動配置的。在 Spring Boot 2.2.1 版本中&#xff0c;有幾種數據源配置可選&#xff0c;它們按照 HikariCP -> Tomcat -> DBCP2 …

使用Qt正則表達式提取全路徑的文件名

問題描述&#xff1a; 給定三個全路徑&#xff0c;例如 path1"C:/Users/asus/Desktop/nefertiti_4465.obj"; path2"C:/Users/asus/Desktop/nefertiti_4465_k1.txt"; path3"C:/Users/asus/Desktop/nefertiti_4465_k2.txt"; 我希望說明path2和pa…

Beyond Compare 3.3.8 build 16340 + Key

本文摘錄自冰點社區&#xff1a;http://forum.z27315.com/topic/14746-beyond-compare-338-build-16340-key/ Download Beyond Compare 3 Current Version: 3.3.8, build 16340, released June 19, 2013 Windows 版本 Windows Standard and Pro EditionsEnglish version 5800k…

hdu 1198 Farm Irrigation

題目鏈接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid1198 題目大意&#xff1a; 有一大塊土地需要澆水&#xff0c;這塊土地由很多的小塊土地&#xff08;有十一種&#xff09;組成&#xff0c;小塊土地上有水溝&#xff0c;問至少需要建幾個井&#xff0c;才能灌…