Java中的字符編碼問題處理心得總結(jié)
當(dāng)面對一串字節(jié)流的時(shí)候,如果不指定它的編碼,其實(shí)際意義是無法知道的。
這句話應(yīng)該也是我們面對“字符轉(zhuǎn)字節(jié),字節(jié)轉(zhuǎn)字符”問題時(shí)候時(shí)刻記在腦子里的。否則亂碼問題可能就接踵而至。
其實(shí)亂碼問題的本質(zhì)就是Encoding和Decoding用的不是一個(gè)編碼,明白了這個(gè)道理就很好解決亂碼問題了。
Java中常見的時(shí)候有如下:
1. String類使用byte[]的構(gòu)造函數(shù) String(byte[] bytes),String類同時(shí)提供了兩個(gè)重載
(1)String(byte[] bytes, Charset charset)
(2)String(byte[] bytes, String charsetName) 就是用來指定編碼的。
2. String類的getBytes函數(shù) byte[] getBytes() 同樣有如下兩個(gè)重載:
(1)byte[] getBytes(Charset charset)
(2) byte[] getBytes(String charsetName)
所有不需指定編碼的都是使用the platform's default charset, 可使用System.getProperty("file.encoding"),Charset.defaultCharset()獲的。
3. PrintStream的 print(String s)同樣設(shè)計(jì)到這個(gè)問題,為此PrintStream的構(gòu)造函數(shù)中除了PrintStream(File file) 還有PrintStream(File file, String csn)
否則the string's characters are converted into bytes according to the platform's default character encoding,
DataOutputStream構(gòu)造時(shí)沒有方法指定編碼,但其提供了一個(gè)writeUTF(String str)
舉開頭的例子說明指定編碼的必要:
如果一個(gè)網(wǎng)頁指定編碼為utf-8, <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />, 頁面上有一個(gè)form,提交到一個(gè)servlet
那么用戶輸入的字符傳過來的字節(jié)流就是按指定編碼encoding的,例如你輸入了"Hello你好",如果是utf-8,那么傳過來的就是如下:
[104, 101, 108, 108, 111, -28, -67, -96, -27, -91, -67]
, 我們看到后面漢字每個(gè)用了3個(gè)字節(jié),這個(gè)可以參考Utf-8的相關(guān)知識。
但如果你頁面指定的是GBK,那傳過來的就不一樣了:
[104, 101, 108, 108, 111, -60, -29, -70, -61]
所以servlet端,當(dāng)使用request.getParameter的時(shí)候內(nèi)部應(yīng)該是調(diào)用
String s = new String(bytes, response.getEncoding())的,如果你response沒有設(shè)置編碼,那么就采用默認(rèn)的編碼null會轉(zhuǎn)為java 平臺的GBK,那中文就變成亂碼了。
所以為了避免亂碼,jsp站點(diǎn)一般設(shè)一個(gè)過濾器,所有的頁面、servet都設(shè)置統(tǒng)一的編碼。response.setEncoding, request.setEncoding.
Java的String內(nèi)部是一個(gè)char[], char是一個(gè)用16位存儲的utf-16編碼的單元。為此,當(dāng)要把字符、字符串轉(zhuǎn)為字節(jié)輸出到文件、網(wǎng)絡(luò),或者從文件、網(wǎng)絡(luò)讀到的字節(jié)流還原為有實(shí)際意義的字符,都要明白其編碼是什么。
幾點(diǎn)心得
1.String類始終是以Unicode編碼形式存儲.
2.注意String.getBytes()的使用:
如果不帶字符集參數(shù),就會依賴于JVM的字符集編碼,LINUX上一般為UNICODE,WINDOWS下一般為GBK.(要想改變JVM缺省字符集編碼,啟動JVM時(shí)用選項(xiàng)-Dfile.encodeing=UTF-8.
為了安全起見,建議始終帶參數(shù)調(diào)用,例如:String s ; s.getBytes("UTF-8")。
3.Charset類非常好用,
(1)Charset.encode 是編碼,即把String按你指定的字符集編碼格式進(jìn)行編碼后輸出字節(jié)數(shù)組。
(2)Charset.decode 是解碼,即把一個(gè)字節(jié)數(shù)組按你指定的字符集編碼格式進(jìn)行解碼后輸出成字符串。
舉例如下:
String s = Charset.defaultCharset().displayName(); String s1 = "我喜歡你,My Love"; ByteBuffer bb1 = ByteBuffer.wrap(s1.getBytes("UTF-8")); for(byte bt:bb1.array()){ System.out.printf("%x",bt); } //char[]用法 char[] chArray={'I','L','o','v','e','你'}; //CharBuffer用法 CharBuffer cb = CharBuffer.wrap(chArray); //重新定位指針 cb.flip(); String s2= new String(chArray); //ByteBuffer用法 ByteBuffer bb2 = Charset.forName("utf-8").encode(cb); // 利用Charset編碼為指定字符集 ByteBuffer bb3 = Charset.forName("utf-8").encode(s1); byte [] b = bb3.array() ; // 利用Charset按指定字符集解碼為字符串 ByteBuffer bb4= ByteBuffer.wrap(b); String s2 = Charset.forName("utf-8").decode(bb4).toString();
相關(guān)文章
java獲得平臺相關(guān)的行分隔符和java路徑分隔符的方法
不同系統(tǒng)平臺下的行分隔符、路徑分隔符等常常不同,如何在Java程序獲取當(dāng)前平臺的分隔符,以及其他系統(tǒng)相關(guān)的狀態(tài)呢?下面是示例程序,需要的朋友可以參考下2014-02-02解決idea web項(xiàng)目中out目錄更新不同步問題
這篇文章給大家介紹了idea web項(xiàng)目中out(maven中是target)目錄更新不同步,導(dǎo)致訪問404的問題,本文給大家分享解決方法,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2020-09-09基于Java解決華為機(jī)試實(shí)現(xiàn)整數(shù)與IP地址間的轉(zhuǎn)換?
這篇文章主要介紹了基于Java解決華為機(jī)試實(shí)現(xiàn)整數(shù)與IP地址間的轉(zhuǎn)換,文章舉例說明圍繞文章主題展開相關(guān)內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-02-02@ConfigurationProperties綁定配置信息至Array、List、Map、Bean的實(shí)現(xiàn)
這篇文章主要介紹了@ConfigurationProperties綁定配置信息至Array、List、Map、Bean的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05SpringCloud實(shí)現(xiàn)灰度發(fā)布的方法步驟
本文主要介紹了SpringCloud實(shí)現(xiàn)灰度發(fā)布的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05