溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

java出現(xiàn)亂碼的原因和解決方法

發(fā)布時(shí)間:2020-06-29 11:06:20 來源:億速云 閱讀:399 作者:Leah 欄目:編程語言

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)java出現(xiàn)亂碼的原因和解決方法,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

java在字符串中統(tǒng)一用Unicode表示。

對(duì)于任意一個(gè)字符串:String string = “測(cè)試字符串”;

如果源文件是GBK編碼,操作系統(tǒng)默認(rèn)環(huán)境編碼也為GBK,那么編譯的時(shí)候,JVM將按照GBK編碼將字節(jié)數(shù)組解析為字符,然后將字符轉(zhuǎn)換為Unicode格式的字節(jié)數(shù)組,作為內(nèi)部存儲(chǔ)(字節(jié)數(shù)組→字符→Unicode字節(jié)數(shù)組)

當(dāng)打印這個(gè)字符串時(shí),JVM根據(jù)操作系統(tǒng)本地的語言環(huán)境,將Unicode轉(zhuǎn)換為GBK,然后操作系統(tǒng)將GBK格式的內(nèi)容顯示出來。

當(dāng)源碼文件是UTF-8, 我們需要通知編譯器源碼的格式,javac -encoding utf-8 … , 編譯時(shí),JVM按照utf-8 解析成字符,然后轉(zhuǎn)換為unicode格式的字節(jié)數(shù)組, 那么不論源碼文件是什么格式,同樣的字符串,最后得到的unicode字節(jié)數(shù)組是完全一致的,顯示的時(shí)候,也是轉(zhuǎn)成GBK來顯示(跟OS環(huán)境有關(guān))

亂碼是如何產(chǎn)生的?

本質(zhì)上都是由于字符串原本的編碼格式與讀取時(shí)解析用的編碼格式不一致導(dǎo)致的。

亂碼指的是程序顯示出來的字符文本無法用任何語言去解讀。一般情況下會(huì)包含大量的?。亂碼問題是所有計(jì)算機(jī)用戶或多或少會(huì)遇到的問題。造成亂碼的原因就是因?yàn)槭褂昧隋e(cuò)誤的字符編碼去解碼字節(jié)流,因此當(dāng)我們?cè)谒伎既魏胃谋撅@示有關(guān)的問題時(shí),請(qǐng)時(shí)刻保持清醒:當(dāng)前使用的字符編碼是什么。只有這樣,我們才能正確分析和處理亂碼問題。

例如最常見的網(wǎng)頁亂碼問題。如果你是網(wǎng)站技術(shù)人員,遇到這樣的問題,需要檢查以下原因:

服務(wù)器返回的響應(yīng)頭Content-Type沒有指明字符編碼

● 網(wǎng)頁內(nèi)是否使用META HTTP-EQUIV標(biāo)簽指定了字符編碼

● 網(wǎng)頁文件本身存儲(chǔ)時(shí)使用的字符編碼和網(wǎng)頁聲明的字符編碼是否一致

java代碼中的亂碼問題如何解決呢?

例如:String s = “測(cè)試字符串”;

System.out.println( new String(s.getBytes(),"UTF-8")); 
//錯(cuò)誤,因?yàn)間etBytes()默認(rèn)使用GBK編碼, 而解析時(shí)使用UTF-8編碼,肯定出錯(cuò)。

其中g(shù)etBytes()是將Unicode轉(zhuǎn)換為操作系統(tǒng)默認(rèn)格式的字節(jié)數(shù)組,即“測(cè)試字符串”的GBK格式,new String (bytes, Charset) 中的charset 是指定讀取byte的方式,這里指定為UTF-8,即把bytes的內(nèi)容當(dāng)做UTF-8來讀取。

如下兩種方式得到的結(jié)果都是正確的,因?yàn)樗鼈兊脑磧?nèi)容編碼和解析用的編碼是一致的。

System.out.println( new String(s.getBytes(),"GBK"));
System.out.println( new String(s.getBytes("UTF-8"),"UTF-8"));

那么,如何利用getBytes 和 new String() 來進(jìn)行編碼轉(zhuǎn)換呢?

網(wǎng)上流傳著一種錯(cuò)誤的方法:

GBK--> UTF-8: new String( s.getBytes("GBK") , "UTF-8);

這種方式是完全錯(cuò)誤的,因?yàn)間etBytes 的編碼與 UTF-8 不一致,肯定是亂碼。

但是為什么在tomcat 下,使用 new String(s.getBytes(“iso-8859-1”) ,”GBK”) 卻可以用呢?

答案是:

tomcat 默認(rèn)使用iso-8859-1編碼, 也就是說,如果原本字符串是GBK的,tomcat傳輸過程中,將GBK轉(zhuǎn)成iso-8859-1了,默認(rèn)情況下,使用iso-8859-1讀取中文肯定是有問題的,那么我們需要將iso-8859-1 再轉(zhuǎn)成GBK, 而iso-8859-1 是單字節(jié)編碼的,即他認(rèn)為一個(gè)字節(jié)是一個(gè)字符, 那么這種轉(zhuǎn)換不會(huì)對(duì)原來的字節(jié)數(shù)組做任何改變,因?yàn)樽止?jié)數(shù)組本來就是由單個(gè)字節(jié)組成的,如果之前用GBK編碼,那么轉(zhuǎn)成iso-8859-1后編碼內(nèi)容完全沒變, 則 s.getBytes(“iso-8859-1”) 實(shí)際上還是原來GBK的編碼內(nèi)容則 new String(s.getBytes(“iso-8859-1”) ,”GBK”) 就可以正確解碼了。 所以說這是一種巧合。

如何正確的將GBK轉(zhuǎn)UTF-8 ? (實(shí)際上是unicode轉(zhuǎn)UTF-8)

//利用getBytes將unicode字符串轉(zhuǎn)成UTF-8格式的字節(jié)數(shù)組,然后用utf-8 對(duì)這個(gè)字節(jié)數(shù)組解碼成新的字符串
new String( s.getBytes("utf-8") , "utf-8");

UTF-8 轉(zhuǎn)GBK原理也是一樣

new String( s.getBytes("GBK") , "GBK");

其實(shí)核心工作都由getBytes(charset)做了。getBytes的JDK描述:Encoding this String into a sequence of bytes using the named charset,storing the result into a new byte array.

OutputStreamWriter w1 = new OutputStreamWriter(new FileOutputStream("D:\\file1.txt"),"UTF-8");
InputStreamReader( stream, charset)

可以幫助我們輕松的按照指定編碼讀寫文件。

上述就是小編為大家分享的java出現(xiàn)亂碼的原因和解決方法了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI