天天看點

編碼小記(未整理-持續更新)

----------------基本概念-------------------------------

一.位:

計算機存儲資訊的最小機關,稱之為位(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 字元,即 "ÖÐ"。

反之,将 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