Qt與MSVC中文亂碼問題的解決方案

2021-10-06 13:59:37 字數 3165 閱讀 2127

一、問題是什麼?

在學習qt程式設計的過程中,大多數人都遇到過中文亂碼的問題。總結起來有三類:

1. qt creator中顯示的漢字變為亂碼,編輯器上方有「could not decode "..." with "utf-8"-encoding. editing not possible.」的錯誤提示。此時,出現亂碼的文件是不可編輯的。如下圖所示,「你好中文!」這5個中文字元變成了亂碼:

2. qt creator中顯示的漢字正常,但編譯的時候會出現「常量中有換行符」等一系列錯誤報警。其實,這也是文字編碼的問題。如下圖所示:

3. 編譯時未報錯,但生成的程式中文亂碼。如下圖所示:

其中,第3條是網上提問的最多的,幾乎是所有使用msvc的初學者都會碰到的問題。很多回答是針對qt4版本的,qt5中不可用。

二、為什麼會出現這些問題?

在解決問題之前,字元編碼知識是必需的。你要知道ascii、gb2312、gbk、unicode、utf-8、utf-16、bom是怎麼回事。此外,你還要明白原始碼字符集、執行字符集是什麼。詳細內容可以在網上搜尋一下,俯拾即是。

1. qt creator的編輯器預設使用utf-8(**頁65001)編碼來讀取文字檔案。而visual studio儲存檔案時預設採用的是本地編碼,對於簡體中文的windows作業系統,這個編碼就是gb2312(**頁936)。如果使用qt creator讀取由visual studio建立的檔案,那麼編輯器就會以utf-8編碼格式讀取gb2312編碼格式的檔案,出現中文亂碼,因為這兩套編碼系統對漢字編碼是不同的。至於英文部分不會亂碼,是因為utf-8和gb2312在單位元組字元部分是相容的。

2. msvc在編譯時,會根據源**檔案有無bom來定義原始碼字符集。如果有bom,則按bom解釋識別編碼;如果沒有,則使用本地字符集,對於簡體中文的windows作業系統就是gb2312。那麼,當msvc遇到乙個沒有bom的utf-8編碼的檔案時,它通常會把檔案看作gb2312的來處理。如果檔案全是英文沒有問題,但如果包含中文,編譯器就會出現誤讀。這種情況下,qt creator編輯器是正常的。但對於msvc編譯器,原**會被它認識成下圖這個樣子:

這是我用everedit指定本地編碼重讀後的結果,可以看到漢字出錯,末端的引號也沒了。

在utf-8中,乙個中文字元(漢字或標點符號)占用3個位元組,「你好中文!」這5個中文字元共占用15個位元組;而在gb2312中,乙個中文字元(漢字或標點符號)占用2個位元組,這時,msvc把utf-8編碼的15個位元組加上後面1個位元組的英文引號合成16個位元組當作8個中文字元處理。之後,msvc在這一行裡直到末尾換行符出現都沒有找到下乙個引號,它以為你把字串在這裡敲回車換行了,於是報警稱「常量中有換行符」,並引出一系列的錯誤。

不過,當以無bom的utf-8編碼的字串正好湊夠偶數個位元組時(比如偶數個漢字,或奇數個漢字加奇數個英文本母),編譯器通常不會報警,因為它以為用gb2312編碼讀出的是正確的。

3. 不管原始檔是何種編碼,只要msvc能夠正確識別,就可以通過編譯。但msvc的執行字符集預設是本地字符集。對我們來說,它生成的可執行檔案中的文字是gb2312編碼的。而生成的qt程式以utf-8編碼來識別gb2312編碼的文字,對於「你好中文!」這幾個字元,採用gb2312編碼後再以uft-8編碼來讀取,就會變成如下的亂碼:

當以無bom的utf-8編碼的字串正好湊夠偶數個位元組時(比如偶數個漢字,或奇數個漢字加奇數個英文本母),反而不會出現亂碼。那是因為,編譯器用gb2312編碼讀出的亂碼本身就是utf-8編碼的,現在又用utf-8解讀,自然就正確了。這純粹是歪打正著。

三、怎麼解決這些問題?

首先,你要確定採用哪種原始碼字符集。你有兩個選擇:

1. 採用本地編碼字符集(不推薦,跨平台時會比較麻煩,但在visual studio環境下配合add-in工具程式設計比較方便);

2. 採用utf-8編碼字符集(推薦,適合跨平台)。

1 「採用本地編碼字符集」方案,解決方法如下:

首先,要把專案中所有的標頭檔案和原始檔全都轉換成gb2312編碼儲存。

話說回來,既然選擇本地字符集,大致上是放棄跨平台了。與其用輕量級的qt creator,不如用visual studio作開發環境更好。

2. 第2個問題:「常量中有換行符」等一系列報警已不存在了。

3. 第3個問題:在字串常量上加qstringliteral巨集或qstring::fromlocal8bit函式,如:

qstring str = "你好中文!";
改為:

qstring str = qstringliteral("你好中文!");
或者:

qstring str = qstring::fromlocal8bit("你好中文!");
不過,在這兩種形式下,你都無法用tr方法來建立翻譯了。

2 「採用utf-8編碼字符集」方案,解決方法如下:

首先,要把專案中所有的標頭檔案和原始檔全都轉換成utf-8+bom編碼儲存。

1. 第1個問題不存在了。

2. 第2個問題也不存在了。

3. 第3個問題,你也可以用上個方案中的方法來解決,但有更好的方法。那就是要用到中文字元的標頭檔案和原始檔開頭加上msvc的乙個巨集:

#if _msc_ver >= 1600

#pragma execution_character_set("utf-8")

#endif

這個巨集告訴msvc,執行字符集是utf-8編碼的,別瞎整成gb2312的!還有個好處,就是能用tr包中文,方便日後的翻譯。最終效果如下:

qt 中文亂碼 Qt中文亂碼問題

接觸了qt,由於習慣中vs,如果使用vs寫qt 剛接觸很快就發現有中文亂碼問題,我的解決方法如下 新建乙個標頭檔案,比如qtchcharset.h,標頭檔案中內容如下 pragma once ifdef q os win q os win 新增後支援gb2312,utf 8 bom,unicode ...

亂碼問題 Qt中文亂碼問題

接觸了qt,由於習慣中vs,如果使用vs寫qt 剛接觸很快就發現有中文亂碼問題,我的解決方法如下 新建乙個標頭檔案,比如qtchcharset.h,標頭檔案中內容如下 pragma once ifdef q os win q os win 新增後支援gb2312,utf 8 bom,unicode ...

QT 中文亂碼問題

1,將設定改為 如果是utf 8編碼,則新增 2,cpp檔案開始新增 pragma execution character set utf 8 根據 qt 的文件 中規定 qstring 的 const char 建構函式是呼叫 fromutf8 構造的。所以要求字串字面量是 utf 8 編碼的位元...