java編碼解碼過程


最近做項目的時候,有時會遇到中文亂碼的問題,網上查詢了很多資料,發現大多都是只講解決方案,並沒有講到為什么要使用這種方案,這種方案的原理是什么?

最典型的就是連接數據庫的URL,我們一般把它放到classpath下的db.properties中,然后盡管我們的java代碼設置了UTF-8,JSP也設置了UTF-8,數據庫也設置了UTF-8,但是插入數據到數據庫中仍然會出現中文亂碼,最后我們的解決方案是在連接數據庫的URL上加上連接使用的編碼格式UTF-8,但是我們會納悶為什么要這么做呢?

下面我們來聊下java編碼的問題,為什么要編碼,有哪些編碼,怎么編碼和解碼,為什么會有中文亂碼,怎么解決中文亂碼。

1.為什么要編碼

這個問題必須要回到計算機是如何表示我們人類能夠理解的符號的,這些符號也就是我們人類使用的語言。由於人類的語言太多,因而表示這些語言的符號太多,無法使用計算機中一個基本的存儲單元---byte來表示,因而必須要經過拆分或一些翻譯工作,才能讓計算機理解我們的語言。我們可以把計算機能夠理解的語言假定為英語,其他語言要能夠在計算機中使用必須經過一次翻譯,把它翻譯成英語。這個翻譯的過程就是 編碼。

所以總的來說,編碼的原因可以總結為:計算機中存儲信息的最小單元是一個字節,即8個bit,所以能表示的字符范圍是0-255個;人類要表示的符號太多,無法用一個字節來完全表示。

要解決這個矛盾必須要有一個新的數據結構char,從char到byte必須編碼。

2.常見的編碼

明白了各種語言需要交流,經過翻譯是必須的,那么又如何來翻譯呢?計算機中提供了多種翻譯方式,常見的右ASCII,ISO-8859-1,GB2312,GBK,UTF-8,UTF-16等。他們可以被看做字典,他們規定了轉化的規則,按照這個規則可以讓計算機正確地標識我們的字符。目前的編碼格式很多,如GB2312,GBK,UTF-8,UTF-16都可以標識一個漢字,那我們到底選擇哪種編碼格式來存儲漢字呢?這就要考慮其他因素呢,是存儲空間重要還是編碼的效率重要。

3.怎么編碼,解碼

以String為例,代碼如下:

String s="這是一段中文字符串";
byte[] b=s.getBytes("UTF-8");
String n=new String(b,"UTF-8");

編碼的用途:把我們用戶能夠認識的語言轉化為計算機能夠認識的語言,一般用在傳輸或者存儲時,也就是涉及到計算機的操作而不是針對用戶而言。

解碼:把字節碼解釋為我們用戶能夠認識的語言。

4.為什么有中文亂碼

第一種情況:使用不能識別中文的字符集來編碼,這種情況比較少見

第二種情況,使用一種字符集來編碼,卻用另一種字符集來解碼,這種比較多見,比如,java代碼采用UTF-8編碼,但是訪問數據庫的時候,數據庫采用GBK來解碼,這就會出現中文亂碼。

Charset使用

Charset charset=Charset.forName("UTF-8");
ByteBuffer byteBuffer=charset.encode(string);
CharBuffer charBuffer=charset.decode(byteBuffer);

5.java中怎么編解碼

String name="I am 小明";
toHex(name.toCharArray());
<span style="font-size:18px; white-space: pre;"></span><pre name="code" class="java">try{
     byte[] iso8859=name.getBytes("ISO-8859-1");
     toHex(iso8859);
     byte[] gb2312=name.getBytes("GB2312");
     toHex(gb2312);
     byte[] gbk=name.getBytes("GBK");
     toHex(gbk);
}
String str="小米";
byte[] b=str.getBytes("UTF-8");
public byte[] getBytes(String charsetName)
            throws UnsupportedEncodingException {
        if (charsetName == null) throw new NullPointerException();
        return StringCoding.encode(charsetName, value, 0, value.length);
    }
 static byte[] encode(String charsetName, char[] ca, int off, int len)
        throws UnsupportedEncodingException
    {
        StringEncoder se = deref(encoder);
        String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
        if ((se == null) || !(csn.equals(se.requestedCharsetName())
                              || csn.equals(se.charsetName()))) {
            se = null;
            try {
                Charset cs = lookupCharset(csn); //生成字符集實例
                if (cs != null)
                    se = new StringEncoder(cs, csn);
            } catch (IllegalCharsetNameException x) {}
            if (se == null)
                throw new UnsupportedEncodingException (csn);
            set(encoder, se);
        }
        return se.encode(ca, off, len);
    }
 private static Charset lookupCharset(String csn) {
        if (Charset.isSupported(csn)) {
            try {
                return Charset.forName(csn);
            } catch (UnsupportedCharsetException x) {
                throw new Error(x);
            }
        }
        return null;
    }
  private StringEncoder(Charset cs, String rcn) {
            this.requestedCharsetName = rcn;
            this.cs = cs;
            this.ce = cs.newEncoder()
                .onMalformedInput(CodingErrorAction.REPLACE)
                .onUnmappableCharacter(CodingErrorAction.REPLACE);
            this.isTrusted = (cs.getClass().getClassLoader0() == null);
        }

原創:https://blog.csdn.net/u010627840/article/details/50407575




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM