----------------基本概念-------------------------------
一.位:
計算機存儲信息的最小單位,稱之爲位(bit),音譯比特,二進制的一個「0」或一個「1」叫一位。
二.字節
字節(Byte)是一種計量單位,表示數據量多少,它是計算機信息技術用於計量存儲容量的一種計量單位,8個二進制位組成1個字節。在ASCII碼中,一個標準英文字母(不分大小寫)佔一個字節位置,一個標準漢字佔二個字節位置。
三.字符
字符是指計算機中使用的文字和符號,好比「一、二、三、A、B、C、~!·#¥%…*()+」等等。 java
-----------------經常使用的編碼的簡單分類(3類)---------------linux
單字節字符編碼:
1. 編碼標準:ISO-8859-1
2. 說明:
最簡單的編碼規則,每個字節直接做爲一個 UNICODE 字符。好比,[0xD6, 0xD0] 這兩個字節,經過 iso-8859-1 轉化爲字符串時,將直接獲得 [0x00D6, 0x00D0] 兩個 UNICODE 字符,即 "ÖÐ"。
反之,將 UNICODE 字符串經過 iso-8859-1 轉化爲字節串時,只能正常轉化 0~255 範圍的字符。windows
ANSI 編碼:
1. 編碼標準:GB2312,BIG5,Shift_JIS,ISO-8859-2等
2. 說明:
把 UNICODE 字符串經過 ANSI 編碼轉化爲「字節串」時,根據各自編碼的規定,一個 UNICODE 字符可能轉化成一個字節或多個字節。編碼
反之,將字節串轉化成字符串時,也可能多個字節轉化成一個字符。好比,[0xD6, 0xD0] 這兩個字節,經過 GB2312 轉化爲字符串時,將獲得 [0x4E2D ] 一個字符,即 '中' 字。操作系統
「ANSI 編碼」的特色:
1. 這些「ANSI 編碼標準」都只能處理各自語言範圍以內的 UNICODE 字符。
2. 「UNICODE 字符」與「轉換出來的字節」之間的關係是人爲規定的。unix
UNICODE 編碼:
1. 編碼標準:UTF-8,UTF-16(BE),UTF-16(LE)等
2. 說明:
與「ANSI 編碼」相似的,把字符串經過 UNICODE 編碼轉化成「字節串」時,一個 UNICODE 字符可能轉化成一個字節或多個字節。code
與「ANSI 編碼」不一樣的是:
1. 這些「UNICODE 編碼」可以處理全部的 UNICODE 字符。
2. 「UNICODE 字符」與「轉換出來的字節」之間是能夠經過計算獲得的。orm
--------------------------------UTF編碼簡介---------------------------------
UTF-8:
1. 對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的 Unicode 碼。所以對於英語字母,UTF-8 編碼和 ASCII 碼是相同的。
2. 對於n字節的符號(n > 1),第一個字節的前n位都設爲1,第n + 1位設爲0,後面字節的前兩位一概設爲10。剩下的沒有說起的二進制位,所有爲這個符號的 Unicode 碼
3. 一種變長的編碼方案,使用 1~6 個字節來存儲ip
Unicode符號範圍 | UTF-8編碼方式
(十六進制) | (二進制)
--------------------+------------------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx內存
UTF-16:
1. 介於 UTF-8 和 UTF-32 之間,使用 2 個或者 4 個字節來存儲,長度既固定又可變。
2. 對於 Unicode 編號範圍在 0 ~ FFFF 之間的字符,UTF-16 使用兩個字節存儲,而且直接存儲 Unicode 編號,不用進行編碼轉換
3. 對於 Unicode 編號範圍在 10000~10FFFF 之間的字符,UTF-16 使用四個字節存儲,具體來講就是:將字符編號的全部比特位分紅兩部分,較高的一些比特位用一個值介於 D800~DBFF 之間的雙字節存儲,較低的一些比特位(剩下的比特位)用一個值介於 DC00~DFFF 之間的雙字節存儲。
4. 位於 0xD800~0xDFFF 之間的 Unicode 編碼是特別爲四字節的 UTF-16 編碼預留的,因此不該該在這個範圍內指定任何字符,也就是該範圍內在unicode裏面不存在對應的unicode編碼
5. UTF-16 要求在制定 Unicode 字符集時必須考慮到編碼問題,因此真正的 Unicode 字符集也不是隨意編排字符的
Unicode符號範圍 | UTF-8編碼方式
(十六進制) | (二進制)
---------------------+----------------------------------------------------------------------
0000 0000-0000 FFFF | (xxxxxxxx xxxx xxxxx) - (xxxxxxxx xxxxxxxx)
0001 0000-0010 FFFF | (yyyyyyyy yyxxxxxx xxxxxxxx xxxxxxxx) - (110110yy yyyyyyyy 110111xx xxxxxxxx)
UTF-32:
1. 一種固定長度的編碼方案,無論字符編號大小,始終使用 4 個字節來存儲
2. 以容納全部的 Unicode 字符,因此直接存儲 Unicode 編號便可,不須要任何編碼轉換。浪費了空間,提升了效率
----------------------名詞解釋-----------------------
unicode:
1. Unicode是爲整合全世界的全部語言文字而誕生的。任何文字在Unicode中都對應一個值, 這個值稱爲代碼點(code point)。代碼點的值一般寫成 U+ABCD 的格式。
2. Unicode是由美國主要計算機制造商聯盟指定的編碼字符集,主要用於克服在建立多語言程序和國際化軟件時使用的不一樣編碼字符集的混亂。 從版本1.1開始,Unicode嚴格保持與ISO / IEC 10646及其擴展兼容。 該聯盟也是ISO工做的重要貢獻者,以進一步發展ISO / IEC 10646
3. CJK就是中日韓的意思。Unicode爲了節省碼位,將中日韓三國語言中的文字統一編碼
ucs-2 & ucs-4:
1. ucs全稱是Universal Multiple-Octet Coded Character Set
2. UCS旨在可用於計算機系統和數據通訊中的內部數據表示
3. 文字和代碼點之間的對應關係就是UCS-2(Universal Character Set coded in 2 octets)。 顧名思義,UCS-2是用兩個字節來表示代碼點,其取值範圍爲 U+0000~U+FFFF。
爲了能表示更多的文字,人們又提出了UCS-4,即用四個字節表示代碼點。 它的範圍爲 U+00000000~U+7FFFFFFF,其中 U+00000000~U+0000FFFF和UCS-2是同樣的。
4. ucs-4結構分爲 group plane row cell,每一部分佔用一個字節,其中當group和plane爲00(16進制)時,是和ucs-2相對應
5. UTF-16是徹底對應於UCS-2的
6. UCS-4最高位爲0
BMP:
1. 基本多語言面板(Basic Multilingual Plane,簡稱 BMP)
2. UCS-2 = BMP = plane 00 of group 00
UTF:
1. UCS Transformation Format
2. UTF-八、UTF-16以及UTF-32都是UCS的具體實現,用來存儲和傳輸以及表示
3. UTF-16保存的最小單位爲2個字節,UTF-32保存的最小單位爲4個字節,因此多字節的編碼涉及到字節擺放順序的問題(大小頭)
BOM:
1. Byte Order Mark
2. 是用來標識字節順序的,只存在於windows平臺中,字節流開頭的「FFFE」或者「FEFF」也被稱爲字符"ZERO WIDTH NO-BREAK SPACE"
3. windows平臺下的UTF-8編碼格式是默認會加上BOM,由於UTF-8不須要BOM來代表字節順序,但能夠用BOM來代表編碼方式,「FFFE」在UTF-8中的表示爲「EF BB BF」(UTF-16的BOM是FEFF),因此若是收到以「EF BB BF」開頭的字節流,則代表這是UTF-8編碼
4. UTF-16或者UTF-32能夠不含有BOM
Big Endian(BE) & Little Endian(LE):
1. ucs-2或者ucs-4中規定的碼點在以UTF-16或者UTF-32表示的時候,字節存放順序的2種
2. 表現爲unicode編碼的數據中的前2個字節爲 "FF FE(Little Endian)",其中windows平臺下的默認的Unicode編碼爲Little Endian的UTF-16
3. 例如「漢」字的Unicode編碼是6C49。那麼寫到文件裏時,到底是將6C寫在前面,仍是將49寫在前 面?若是將6C寫在前面,就是Big Endian。若是將49寫在前面,就是Little Endian
大端,高位存儲在內存地址的低位
小端,低位存儲在內存地址的低位
4. unix或者linux相關的平臺使用無bom的utf8做爲標準的緣由是:一切皆文件,一切文件皆是流,一個流能夠被任意的切斷,獨立解析,而不會改變含義。因此它不能有頭,也不能有結尾。因爲頭根本不存在,因此bom不容許存在
5. windows平臺使用帶BOM的UTF-8編碼的緣由是:系統缺省都是用戶當前代碼頁(code page),當前代碼頁不是utf8,這樣,utf8做爲非當前代碼頁格式就沒法識別
ASCII:
1.美國(國家)信息交換標準(代)碼(America Standard Code for Information Interchange)
2.ISO-8859-1是單字節編碼,是以8位做爲一個表示單元,至關因而ASCII的擴展,是徹底兼容ASCII
3.Unicode只與ASCII兼容(更準確地說,是與ISO-8859-1兼容)
ANSI:
1. 美國國家標準協會(American National Standard Institite)
2. ANSI編碼是指不一樣地區或者國家的編碼標準,好比GB23十二、GBK或者Big-5編碼標準,通常都是使用2個字節來表示一個字符,但也有例外,好比GB18030編碼標準中的一些漢字是用3個字節表示,不一樣的ANSI編碼是互不兼容的
3. 在windows或者linux中存在內碼頁(code page)的概念,也就是不一樣的非unicode編碼是存在不一樣的頁的,好比GBK編碼在CP936頁,UTF-8的代碼頁是65001
4. 在操做系統內部,好比windows系列的內碼就是Unicode編碼,是以UTF-16來表示的,只要安裝了對應的代碼頁,則能夠正確顯示出字符,記事本中選擇ANSI編碼保存則是使用系統缺省的編碼格式存儲數據,能夠經過修改系統的地區來達到修改缺省的編碼格式
5. 內碼是指操做系統內部的字符編碼,微軟通常將缺省代碼頁指定的編碼說成是內碼,在確認了內碼後,系統將按照當前的缺省代碼頁去解釋文本文件裏的字節流
GB2312:
1. 用兩個數來編碼漢字和中文符號。第一個數稱爲「區」,第二個數稱爲「位」。因此也稱爲區位碼
2. GB2312的原文仍是區位碼,從區位碼到內碼,須要在高字節和低字節上分別加上A0
3. 「啊」的區位碼是1601,寫成16進制是0x10,0x01。這和計算機普遍使用的ASCII編碼衝突。爲了兼容00-7f的ASCII編碼,咱們在區位碼的高、低字節上分別加上A0。這樣「啊」的編碼就成爲B0A1,咱們將加過兩個A0的編碼也稱爲GB2312編碼
(從區位碼到內碼須要在高、低字節上分別加上A0),可是GB2312的原文仍是區位碼
-----------------誤解糾正-----------------------
誤解:「ISO-8859-1 是國際編碼?」
非也。iso-8859-1 只是單字節字符集中最簡單的一種,也就是「字節編號」與「UNICODE 字符編號」一致的那種編碼規則。當咱們要把一個「字節串」轉化成「字符串」,而又不知道它是哪種 ANSI 編碼時,先暫時地把「每個字節」做爲「一個字符」進行轉化,不會形成信息丟失。而後再使用 bytes = string.getBytes("iso-8859-1") 的方法可恢復到原始的字節串。
誤解:「Java 中,怎樣知道某個字符串的內碼?」
Java 中,字符串類 java.lang.String 處理的是 UNICODE 字符串,不是 ANSI 字符串。咱們只須要把字符串做爲「抽象的符號的串」來看待。所以不存在字符串的內碼的問題。
當 UNICODE 被支持後,Java 中的 String 是以字符的「序號」來存儲的,不是以「某種編碼的字節」來存儲的,所以已經不存在「字符串的編碼」這個概念了。只有在「字符串」與「字節串」轉化時,或者,將一個「字節串」當成一個 ANSI 字符串時,纔有編碼的概念。
用每「一個字節」就是「一個字符」的轉化方法,實際上也就等同於採用 ISO-8859-1 進行轉化。所以,咱們經常使用 bytes = string.getBytes("iso-8859-1") 來進行逆向操做,獲得原始的「字節串」。而後再使用正確的 ANSI 編碼,好比 string = new String(bytes, "GB2312"),來獲得正確的「UNICODE 字符串」。
-------------------------寬字符和窄字符(多字節字符)-------------------------------------
1. 有的編碼方式採用 1~n 個字節存儲,是變長的,例如 UTF-八、GB23十二、GBK 等;若是一個字符使用了這種編碼方式,咱們就將它稱爲多字節字符,或者窄字符。
2. 有的編碼方式是固定長度的,無論字符編號大小,始終採用 n 個字節存儲,例如 UTF-3二、UTF-16 等;若是一個字符使用了這種編碼方式,咱們就將它稱爲寬字符。
3. Unicode 字符集可使用窄字符的方式存儲,也可使用寬字符的方式存儲;GB23十二、GBK、Shift-JIS 等國家編碼通常都使用窄字符的方式存儲;ASCII 只有一個字節,無所謂窄字符和寬字符。