国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

關于UTF-8所占用的字節以及UTF-8與GB2312之間的關系

tianhang / 1936人閱讀

摘要:一規則下的漢字使用編碼方式的文件,一個漢字所占用的是三個字節,而其他字母控制字符之類還是按照的編碼方式,即占一個字節。

一、UTF-8規則下的漢字

  使用UTF-8編碼方式的文件,一個漢字所占用的是三個字節(byte),而其他字母控制字符之類還是按照ASCII的編碼方式,即占一個字節。為了在解碼的時候區分,經對三千個常用漢字的測試發現,在漢字所占用的三個字節當中:

一個字節轉換為10進制的范圍為:[-28 ~ -23]

第二個字節和第三個字節的10進制范圍均為:[-128 ~ -65]

???????這樣在比如new String(byte[] b)類的函數在解碼的時候,就能夠通過字節為正來判斷是ASCII字符,如是在[-28 ~ -23]范圍內則是一個漢字的開始,并且后面還有兩個[-128 ~ -65]范圍的字節時,就會把這三個字節轉換為一個漢字。
  測試代碼如下:

public class FileInputStreamTest
{
    public static void main(String[] args) throws IOException
    {

        FileInputStream fis = new FileInputStream("srcIO系統漢字");
        List> listTreeSet =new ArrayList<>();
        for(int i=0;i<3;i++)
            listTreeSet.add(new TreeSet());
        
        byte[] bbuf = new byte[3];
        int hasRead = 0;
            while ((hasRead = fis.read(bbuf)) > 0 )
            {
                //System.out.println(new String(bbuf , 0 , hasRead ));//可用來查看當前bbuf字節數組表示的一個漢字
                for(int i=0;i<3;i++)
                    if(bbuf[i]<0) {
                    //這里用了這一句是因為eclispe里面一行有長度限制,所以將漢字分成了三行,因為每行末換行符和回車符各占一個字節,再在下行初加上一個字母比如a就可以使得三個字符被一起讀走而不影響漢字字節的讀取順序,其他的每三個字符仍然是一個漢字
                            listTreeSet.get(i).add((int) bbuf[i]);
                    }
            }
            for(int i=0;i<3;i++)
            System.out.println("第"+(i+1)+"個字節:"+listTreeSet.get(i));
        fis.close();
    }
}
/**
第1個字節:[-28, -27, -26, -25, -24, -23]
第2個字節:[-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, -66, -65]
第3個字節:[-128, -127, -126, -125, -124, -123, -122, -121, -120, -119, -118, -117, -116, -115, -114, -113, -112, -111, -110, -109, -108, -107, -106, -105, -104, -103, -102, -101, -100, -99, -98, -97, -96, -95, -94, -93, -92, -91, -90, -89, -88, -87, -86, -85, -84, -83, -82, -81, -80, -79, -78, -77, -76, -75, -74, -73, -72, -71, -70, -69, -68, -67, -66, -65]

**/

java的char類型,只有兩個字節,在采用utf-8編碼時,為什么可以存儲漢字?:

  Unicode是一種字符集(charset),即字符的集合。UTF-8與UTF-16都是是一種建立在Unicode字符集上面的編碼方式(encoding),是將Unicode字符集里的字符轉換成具體的二進制流。所不同的是在UTF-8和UTF-16當中,將Unicode中一個漢字編碼成二進制后,分別是三個字節大小和兩個字節大小。
  在一個Java文件(例如該文件為UTF-8編碼)里面寫上這樣一句話char a = "猿";如圖所示,編譯后生成的class文件是UTF-8的,不過是modified的(可能與通常的utf-8的機制有些許區別),一個漢字仍然是占三個字節的,但關鍵在于運行的時候會將其轉換為UTF-16編碼方式下的,這樣在運行的時候char類型當中仍然只放有兩個字節,所以java編譯器也是允許用char來存放中文字符的。
詳細參考回答java編譯器編碼和JVM編碼問題?

二、UTF-8與GB2312之間的關系

  關于字符集與編碼方式的關系:字符集就是字符的集合,如ASCII,GBK,BIG5,Unicode等,編碼方式是即可理解為定義在字符集上的映射規則。
  對于unicode字符集,有utf8,utf16,utf32等多種編碼方式,但對于其他字符集,只有一種默認的編碼方式:比如,ASCII,GBK,GB2312等,不僅僅代表字符集,同時也代表了(默認的)的編碼方式。

復制文件時的亂碼

  在win10中默認的字符集是gb2312,。用notepad++隨便打開一個txt文件,在右下角就能看到字符集

  而我自己在eclipse里面設置的編碼是utf-8(對應字符集是不同的,所以)

  所以對于我們在windows記事本中創建的txt文件直接復制到eclipse中就會出現亂碼,如下所示,因為兩個文件采用了不同的字符集,發生了亂碼:


而且經過測試這種GB2312與UTF-8之間的相互轉換的效果是不可逆的(因為發生了信息丟失),代碼如下:

public class TestCharset {
    public static void main(String[] args) throws IOException {
        Charset utf8 = StandardCharsets.UTF_8;
        Charset gbk2312 = Charset.forName("GB2312");

        //將某段文字以gb2312編碼后得到的字節數組,再以utf-8進行解碼得到的文字是亂碼,并且這段亂碼中丟失了信息。
        //所以不能再轉換回utf-8了
        ByteBuffer BytesExpressTextOnGBK2312 = gbk2312.encode("天生我才必有用");
        CharBuffer Decode_BytesExpressTextOnGBK2312_UseUTF8 = utf8.decode(BytesExpressTextOnGBK2312);
        System.out.println("將"天生我才必有用"按照GBK2312規則編碼后得到的字節數組,再以UTF8解碼得到的文字:
"+Decode_BytesExpressTextOnGBK2312_UseUTF8);
        
        ByteBuffer Encode__Decode_BytesExpressTextOnGBK2312_UseUTF8__UseUTF8 = utf8.encode(Decode_BytesExpressTextOnGBK2312_UseUTF8);
        CharBuffer Decode___Encode__Decode_BytesExpressTextOnGBK2312_UseUTF8__UseUTF8___UseGBK2312 = gbk2312.decode(Encode__Decode_BytesExpressTextOnGBK2312_UseUTF8__UseUTF8);
        System.out.println("將上面的文字再反向以UTF8編碼得到的字節數組,再按照GBK2312解碼得到的文字:
"+Decode___Encode__Decode_BytesExpressTextOnGBK2312_UseUTF8__UseUTF8___UseGBK2312);
        
        System.out.println("-----------------------------------------------分割線-----------------------------------------------");
        
        //同樣 將某段文字以utf8編碼后得到的字節數組,再以utf-8進行解碼得到的文字是亂碼,并且這段亂碼中丟失了信息
        //逆向后大部分文字也不能恢復,不過比上面的完全不能恢復好了一些
        ByteBuffer BytesExpressTextOnUTF8 = utf8.encode("天生我才必有用");
        CharBuffer Decode_BytesExpressTextOnUTF8_UseGBK2312 = gbk2312.decode(BytesExpressTextOnUTF8);
        System.out.println("將"天生我才必有用"按照UTF8規則編碼后得到的字節數組,再以GBK2312解碼得到的文字:
"+Decode_BytesExpressTextOnUTF8_UseGBK2312);
        
        ByteBuffer Encode__Decode_BytesExpressTextOnUTF8_UseGBK2312__UseGBk2312= gbk2312.encode(Decode_BytesExpressTextOnUTF8_UseGBK2312);
        CharBuffer Decode___Encode__Decode_BytesExpressTextOnUTF8_UseGBK2312__UseGBk2312___UseUTF8 = utf8.decode(Encode__Decode_BytesExpressTextOnUTF8_UseGBK2312__UseGBk2312);
        System.out.println("將上面的文字再反向以GBK2312編碼得到的字節數組,再按照UTF8解碼得到的文字:
"+Decode___Encode__Decode_BytesExpressTextOnUTF8_UseGBK2312__UseGBk2312___UseUTF8);
    }
}
/**
將"天生我才必有用"按照GBK2312規則編碼后得到的字節數組,再以UTF8解碼得到的文字:
????????????
將上面的文字再反向以UTF8編碼得到的字節數組,再按照GBK2312解碼得到的文字:
錕斤拷錕斤拷錕揭才憋拷錕斤拷錕斤拷
-----------------------------------------------分割線-----------------------------------------------
將"天生我才必有用"按照UTF8規則編碼后得到的字節數組,再以GBK2312解碼得到的文字:
澶╃??????蹇?????
將上面的文字再反向以GBK2312編碼得到的字節數組,再按照UTF8解碼得到的文字:
天?????????????
**/
復制文字時可能不會出現亂碼

  那為什么我們直接從txt復制文字過去就不會變成亂碼呢?
  目前找到的比較信服的觀點是:對于復制粘貼文字而言,虛擬機軟件(比如我們的java虛擬機)、遠程主機軟件都會有一個「介于兩系統之間的」剪貼板,「連接起」這兩個系統的各自剪貼板,并做一些編碼格式轉換的工作。這樣我們復制過去的文字就肯定不會出現亂碼了。
  按照這個說法,推測就是說eclispe當中會有一個針對windows系統的剪貼板,比如當我們從txt中復制過去的文字(實際上應該是字節數組)與eclispe中的我們設置的編碼不同的話,先會按照txt原本的編碼規則對字節數組進行解碼得到文字,然后再按照eclispe我們設置的編碼規則進行編碼,這然后就可以粘貼過去而不出錯了。但也只是一種推測可能原理不是這樣,但肯定的是做了一些編碼轉換的工作。

擴展文章:Java編碼問題原因以及解決

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/72377.html

相關文章

  • 細說Unicode(一) Unicode初認識

    摘要:所以中國人自己創造了一種字符編碼,每個漢字和符號用兩個字節來表示。第一個字節稱為高位字節,第二個字節稱為低位字節。而目前為止我們使用最廣泛的中文編碼還是。 網站開發中經常會被亂碼問題困擾。知道文件編碼錯誤會導致亂碼,但對其中的原理卻知之甚少。偶然從某篇文章了解了Unicode,發現從這條線出發也牽引出了一系列缺失的知識點。通過研讀文章,基本了解了一些以前不明白的問題,所以整理了幾篇,從...

    loostudy 評論0 收藏0
  • PyTips 0x09 - Python 中 Unicode 正確用法

    摘要:只包含了個基本拉丁字母阿拉伯數目字和英式標點符號一共個字符,因此只需要不占滿一個字節就可以存儲,而則涵蓋的數據除了視覺上的字形編碼方法標準的字符編碼外,還包含了字符特性,如大小寫字母,共可包含個字符,而到現在只填充了其中的個位置。 項目地址:https://git.io/pytips 0x07 和 0x08 分別介紹了 Python 中的字符串類型(str)和字節類型(byte),以及...

    shenhualong 評論0 收藏0
  • 編碼-1

    摘要:關于的參考知乎上的一個回答傳送門以我自己的理解就是首先得分清楚編碼問題在不同的環境中,編碼是不同的。但是如果換成的是知乎的話,則表示的是將這個漢字用編碼的形式存放。 文章啟發來源: cnblogs 阮一峰 知乎 字符編碼方式 note from wiki: 從維基百科上得到的一些理解,一個字符的unicode編碼是確定的,但是在傳輸過程中,由于不同系統平臺的設計不一致,所以對uni...

    IamDLY 評論0 收藏0
  • 字符編碼那些事

    摘要:字符編碼的那些事前言之前看到中對擴展了不少新特性,字符串操作更加友好,比如,,。其中涉及到不少字符編碼的知識,為了更好理解這些新特性,本文對字符編碼相關知識做一個較全面的梳理和總結。 字符編碼的那些事 前言 之前看到ES6中對String擴展了不少新特性,字符串操作更加友好,比如u{1f914},codePointAt(),String.fromCodePoint()。其中涉及到不少字...

    shadajin 評論0 收藏0
  • 字符編碼那些事

    摘要:字符編碼的那些事前言之前看到中對擴展了不少新特性,字符串操作更加友好,比如,,。其中涉及到不少字符編碼的知識,為了更好理解這些新特性,本文對字符編碼相關知識做一個較全面的梳理和總結。 字符編碼的那些事 前言 之前看到ES6中對String擴展了不少新特性,字符串操作更加友好,比如u{1f914},codePointAt(),String.fromCodePoint()。其中涉及到不少字...

    kviccn 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<