Windows上.java和.class文件字符集編碼關係幷包括C/C++上的類同分析

【摘要】Windows系統默認採用GBK字符集,所以致使沒法使用UTF-8解碼。本文在首先說明Windows上使用的字符集,後分析了JAVA下.java、.class、javac之間的字符集關係,以及分析了VS的C/C++項目的源文件、二進制文件與編譯器間的字符集關係。最後總結:在javac的使用中,最好採用-encoding參數指明.java文件使用的字符集,以避免形成不可恢復的中文亂碼
【問題重現】
JAVA項目中,因爲源文件存儲採用不一樣的字符集致使項目輸出亂碼。當採用GBK存儲源文件,正常符出」中文「,而採用UTF-8存儲源文件,卻輸出亂碼。
下圖爲採用UTF-8存儲源文件,卻輸出亂碼:

下圖爲採用GBK存儲源文件,正常輸出:

【1、Windows系統默認字符集】
1980年,中國製定了GB2310-80,一共收錄了7445個字符。1993年,Unicode 1.1版本推出,收錄20902個漢字,中國製定了等同於Unicode 1.1版本的「GB 13000.1-93」,簡稱爲GB13000。微軟對GB2312-80擴展,並收錄了GB13000和Unicode1.1之中的漢字,制定了GBK編碼。在Windows中使用代碼頁CP936表示。以下圖,在控制檯中使用chcp命令能夠查看Windows使用的字符集。
GBK是Windows中文系統默認的字符集

【2、VS下C/C++項目源文件、二進制文與編譯器的關係】
筆者使用的VC編譯器版本是19.00.24210,使用的VS版本的VS2015。
衆所周知,每一個文件保存時都會選擇指定的字符集,即源文件在Windows上的保存時使用的字符集能夠選擇GBK和UTF-8形式,在中文的Windows 7系統上,VS默認存儲源文件的字符集是GBK。
使用VC編譯器編譯成二進制可執行文件後,二進制文件所使用的字符集符合如下表格。其中帶BOM的UTF8表示在文件開頭使用三個字符做爲BOM頭,標識文件採用的是UTF8字符集java

源文件字符集 編譯後的二進制文件字符集
GBK GBK
UTF-8(帶BOM) GBK
UTF-8 UTF8


【3、JAVA下.java、.class、JVM、輸出控制檯之間的關係】
在阿里,許多人使用intellij idea做爲IDE開發JAVA應用,而intellij idea默認使用UTF8字符集,以下圖,IDE Encoding表示整個IDE使用UTF8編碼,Project Encoding表示本項目使用UTF8編碼。

JAVA下,.java文件和.class文件的字符集關係以下表,好比對於.java中的「中文」字符串str,.class中的字符串有三種狀況:①.java以GBK格式保存,即str以GBK格式保存內容「中文」,通過javac編譯後,.class中str變爲UTF-8保存的"中文「;②.java以UTF-8(無BOM)保存,即str以UTF-8保存內容」中文「,通過javac編譯後,.class中str變爲UTF-8保存的"涓枃",變爲亂碼;③.java以UTF-8(有BOM)保存,沒法經過編譯。ide

.java文件字符集 .class文件字符集
GBK UTF-8
UTF-8(無BOM) UTF-8(可是中文已經亂碼)
UTF-8(有BOM) 編譯失敗沒法生成.class文件


針對上述的第二種狀況,爲何.class保存了UTF-8的亂碼呢?這是因爲.class必定是使用unicode字符集,即兼容UTF8,而.java可使用任意字符集。JAVA的生成過程使用字符集以下:」.java(任意編碼) —> .class(Unicode) —> JVM內(Unicode)「。生成亂碼是因爲javac把UTF8格式的.java文件當成了GBK格式,由於javac中能夠經過-encoding指定.java的字符集,而沒有指定的狀況將默認.java爲系統採用字符集。因爲沒有使用-encoding,javac將已是UTF-8的.java文件當成GBK文件處理,從而致使亂碼。具體可見:https://www.zhihu.com/question/30977092 編碼

相關文章
相關標籤/搜索