编码小记(未整理-持续更新)
----------------基本概念-------------------------------
一.位:
計算機存儲信息的最小單位,稱之為位(bit),音譯比特,二進制的一個“0”或一個“1”叫一位。
二.字節
字節(Byte)是一種計量單位,表示數據量多少,它是計算機信息技術用于計量存儲容量的一種計量單位,8個二進制位組成1個字節。在ASCII碼中,一個標準英文字母(不分大小寫)占一個字節位置,一個標準漢字占二個字節位置。
三.字符
字符是指計算機中使用的文字和符號,比如“1、2、3、A、B、C、~!·#¥%…*()+”等等。
-----------------常用的編碼的簡單分類(3類)---------------
單字節字符編碼:
1. 編碼標準:ISO-8859-1
2. 說明:
最簡單的編碼規則,每一個字節直接作為一個 UNICODE 字符。比如,[0xD6, 0xD0] 這兩個字節,通過 iso-8859-1 轉化為字符串時,將直接得到 [0x00D6, 0x00D0] 兩個 UNICODE 字符,即 "?D"。
反之,將 UNICODE 字符串通過 iso-8859-1 轉化為字節串時,只能正常轉化 0~255 范圍的字符。
ANSI 編碼:
1. 編碼標準:GB2312,BIG5,Shift_JIS,ISO-8859-2等
2. 說明:
把 UNICODE 字符串通過 ANSI 編碼轉化為“字節串”時,根據各自編碼的規定,一個 UNICODE 字符可能轉化成一個字節或多個字節。
反之,將字節串轉化成字符串時,也可能多個字節轉化成一個字符。比如,[0xD6, 0xD0] 這兩個字節,通過 GB2312 轉化為字符串時,將得到 [0x4E2D ] 一個字符,即 '中' 字。
“ANSI 編碼”的特點:
1. 這些“ANSI 編碼標準”都只能處理各自語言范圍之內的 UNICODE 字符。
2. “UNICODE 字符”與“轉換出來的字節”之間的關系是人為規定的。
UNICODE 編碼:
1. 編碼標準:UTF-8,UTF-16(BE),UTF-16(LE)等
2. 說明:
與“ANSI 編碼”類似的,把字符串通過 UNICODE 編碼轉化成“字節串”時,一個 UNICODE 字符可能轉化成一個字節或多個字節。
與“ANSI 編碼”不同的是:
1. 這些“UNICODE 編碼”能夠處理所有的 UNICODE 字符。
2. “UNICODE 字符”與“轉換出來的字節”之間是可以通過計算得到的。
?
--------------------------------UTF編碼簡介---------------------------------
UTF-8:
1. 對于單字節的符號,字節的第一位設為0,后面7位為這個符號的 Unicode 碼。因此對于英語字母,UTF-8 編碼和 ASCII 碼是相同的。
2. 對于n字節的符號(n > 1),第一個字節的前n位都設為1,第n + 1位設為0,后面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的 Unicode 碼
3. 一種變長的編碼方案,使用 1~6 個字節來存儲
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-8、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編碼是指不同地區或者國家的編碼標準,比如GB2312、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-8、GB2312、GBK 等;如果一個字符使用了這種編碼方式,我們就將它稱為多字節字符,或者窄字符。
2. 有的編碼方式是固定長度的,不管字符編號大小,始終采用 n 個字節存儲,例如 UTF-32、UTF-16 等;如果一個字符使用了這種編碼方式,我們就將它稱為寬字符。
3. Unicode 字符集可以使用窄字符的方式存儲,也可以使用寬字符的方式存儲;GB2312、GBK、Shift-JIS 等國家編碼一般都使用窄字符的方式存儲;ASCII 只有一個字節,無所謂窄字符和寬字符。?
轉載于:https://www.cnblogs.com/linusflow/p/10049961.html
總結
以上是生活随笔為你收集整理的编码小记(未整理-持续更新)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 猫打疫苗多少钱啊?
- 下一篇: 求一个关于微信的个性签名。