Java的编码解码
Java的編碼解碼
前言:
介紹編碼和解碼之前,我們先了解一下我們的計算機,計算機中存儲數據的具體單位是存儲單元,
一個最小的信息單元就是“位”(bit),一"位"只能表示0和1中的一個,即一個二進制位;
“字節”(Byte):是由相連8個位組成的信息存儲單位,它是目前計算機最基本的存儲單位,一個字節通常可以存儲一個字符(如字母、數字等)。只有字節才有地址的概念。對一種計算機的存儲設備以字節為單位賦予的地址稱為字節編址;也是目前計算機最基本的存儲單元編址;
java的基本數據類型:
| byte | 8位 | 最大存儲數據量是255,存放的數據范圍是-128~127之間 |
| short | 16位 | 最大數據存儲量是65536,數據范圍是-32768~32767之間 |
| int | 32位 | 最大數據存儲容量是2的32次方減1,數據范圍是負的2的31次方到正的2的31次方減1 |
| long | 64位 | 最大數據存儲容量是2的64次方減1,數據范圍為負的2的63次方到正的2的63次方減1 |
| float | 32位 | 數據范圍在3.4e-45~1.4e38,直接賦值時必須在數字后加上f或F |
| double | 64位 | 數據范圍在4.9e-324~1.8e308,賦值時可以加d或D也可以不加 |
| boolean | 只有true和false兩個取值 | |
| char | 16位 | 存儲Unicode碼,用單引號賦值 |
進入今天的正題:
首先要知道編碼和解碼是char和byte兩個數據類型之間轉換中產生的;
為什么要編碼?
最直接的回答就是防止我們的中文和一些特殊字符出現亂碼的現象;
詳細點講就是計算機只能識別0和1兩個數字,所有的符號和文字都必須經過轉換編碼才能“翻譯”成我們計算機認識的“語言”,相反也是,我們要想顯示出我們能讀懂的“語言”也必須要進行相應的解碼才能從計算機中顯示出我們能看懂的文字;
總的來說編碼的原因有:
如何編碼和解碼呢?
那就是通過一種特定的編碼格式轉換,其實現在有很多中的編碼格式,只要讓計算機按照規定的編碼格式進行轉化,就可以顯示成我們自己的字符。那現在就介紹一下目前最常見的一些編碼格式;
首先我們要知道編碼和編碼格式是有區別的?
編碼就是一個編號(數字)到字符的一種映射關系,是一種一對一的映射關系。Unicode和ASCII 就是屬于兩種編碼,但這兩種編碼能編碼的范圍不同,Unicode 能編碼的范圍要更大一些,幾乎能覆蓋現存的所有字符(Java語言使用的就是該碼表);
ASCII碼
在計算機種中,1 字節對應 8 位二進制數,而每位二進制數有 0、1 兩種狀態,因此 1 字節可以組合出 256 種狀態。如果這 256 中狀態每一個都對應一個符號,就能通過 1 字節的數據表示 256 個字符。美國人于是就制定了一套編碼(其實就是個字典),描述英語中的字符和這 8 位二進制數的對應關系,這被稱為 ASCII 碼。
ASCII 碼一共定義了 128 個字符,例如大寫的字母 A 是 65(這是十進制數,對應二進制是0100 0001)。這 128 個字符只使用了 8 位二進制數中的后面 7 位,最前面的一位統一規定為 0。
Unicode
Unicode 只是一個字符集,規定了符合對應的二進制代碼,至于這個二進制代碼如何存儲則沒有任何規定。它的想法很簡單,就是為每個字符規定一個用來表示該字符的數字,僅此而已。
Unicode編碼方案
之前提到,Unicode 沒有規定字符對應的二進制碼如何存儲。以漢字“漢”為例,它的 Unicode 碼點是 0x6c49,對應的二進制數是 110110001001001,二進制數有 15 位,這也就說明了它至少需要 2 個字節來表示。可以想象,在 Unicode 字典中往后的字符可能就需要 3 個字節或者 4 個字節,甚至更多字節來表示了。
這就導致了一些問題,計算機怎么知道你這個 2 個字節表示的是一個字符,而不是分別表示兩個字符呢?這里我們可能會想到,那就取個最大的,假如 Unicode 中最大的字符用 4 字節就可以表示了,那么我們就將所有的字符都用 4 個字節來表示,不夠的就往前面補 0。這樣確實可以解決編碼問題,但是卻造成了空間的極大浪費,如果是一個英文文檔,那文件大小就大出了 3 倍,這顯然是無法接受的。
于是,為了較好的解決 Unicode 的編碼問題, UTF-8 和 UTF-16 兩種當前比較流行的編碼方式誕生了。當然還有一個 UTF-32 的編碼方式,也就是上述那種定長編碼,字符統一使用 4 個字節,雖然看似方便,但是卻不如另外兩種編碼方式使用廣泛。
對于編碼格式目前最常見的是UTF-8、GBK,它們都是用來序列化或存儲 Unicode 編碼的數據的,但是分別是2中不同的格式,他們都是 Unicode 的實現方式,當然也還有很多,這里就先介紹這兩種啦。
-
GBK
全稱叫《漢字內碼擴展規范》,是國家技術監督局為 windows95 所制定的新的漢字內碼規范,它的出現是為了擴展 GB2312,加入更多的漢字,它的編碼范圍是 8140~FEFE(去掉 XX7F)總共有 23940 個碼位,它能表示 21003 個漢字,它的編碼是和 GB2312 兼容的,也就是說用 GB2312 編碼的漢字可以用 GBK 來解碼,并且不會有亂碼。
-
UTF-8
UTF-8 采用了一種變長技術,每個編碼區域有不同的字碼長度。不同類型的字符可以是由 1~6 個字節組成。
編碼規則:
使用utf-8進行編碼解碼
“漢”的 Unicode 碼點是 0x6c49(110 1100 0100 1001),通過上面的對照表可以發現,0x0000 6c49 位于第三行的范圍,那么得出其格式為 1110xxxx 10xxxxxx 10xxxxxx。接著,從“漢”的二進制數最后一位開始,從后向前依次填充對應格式中的 x,多出的 x 用 0 補上。這樣,就得到了“漢”的 UTF-8 編碼為 11100110 10110001 10001001,轉換成十六進制就是 0xE6 0xB7 0x89。
解碼的過程也十分簡單:如果一個字節的第一位是 0 ,則說明這個字節對應一個字符;如果一個字節的第一位1,那么連續有多少個 1,就表示該字符占用多少個字節。
java中編解碼場景
流讀取文件,其中就存在著字符與字節之間的轉換; InputStreamReader 類就是關聯字節到字符的橋梁,它負責在 I/O 過程中處理讀取字節到字符的轉換;
// 創建指定字符集的 InputStreamReader InputStreamReader(InputStream in, String CharsetName) // 創建使用指定字符集的 OutputStreamWriter OutputStreamWriter(OutputStream out, String CharsetName)處理字符串編碼問題
//獲取utf-8對應的的字符集 Charset charset = Charset.forName("utf-8"); //將字符串通過utf-8進行編碼轉化成字節 byte[] bytes = str.getBytes(charset); //再將字節根據相同的編碼格式進行解碼 String string = new String(bytes, "utf-8"); System.out.println(string);處理請求參數傳遞編碼問題
URLEncoder.encode(strUri, "UTF-8"); URLDecoder.decode(strUri, "UTF-8");值得一看的相關文章:https://blog.csdn.net/troyaninpc/article/details/79476751
下一篇:session會話理解
總結
- 上一篇: 使用iText处理pdf文件的入门级教程
- 下一篇: 富文本编辑器在Java中使用