部分參考文章鏈接:
https://www.cnblogs.com/cthon/p/9297232.html
https://blog.csdn.net/qq_52102933/article/details/126595077
1. ASCII碼
ASCII碼,實際范圍為【00000000~01111111】0~127,,它是American Standard Code for Information Interchange的縮寫(美國標准信息交換代碼),已被國際標准化組織ISO采納,作為國際通用的信息交換標准代碼。
在計算機內部, 所有的信息最終都表示為一個二進制的字符串. 每一個二進制位(bit)有0和1兩種狀態, 因此八個二進制位就可以組合出 256種狀態, 這被稱為一個字節(byte). 也就是說, 一個字節一共可以用來表示256種不同的狀態, 每一個狀態對應一個符號, 就是256個符號, 從 0000000到11111111.上個世紀60年代, 美國制定了一套字符編碼, 對英語字符與二進制位之間的關系, 做了統一規定. 這被稱為ASCII碼, 一直沿用至今.ASCII碼一共規定了128個字符的編碼, 這128個符號(包括32個不能打印出來的控制符號), 只占用了一個字節的后面7位, 最前面的1位統一規定為0.
其中:
0~31及127(共33個)是控制字符或通信專用字符(其余為可顯示字符)
32~126(共95個)是字符(32是空格),其中48~57為0到9十個阿拉伯數字。
65~90為26個大寫英文字母,97~122號為26個小寫英文字母,其余為一些標點符號、運算符號等。
ASCII碼表具體情況可以
ASCII缺點
ASCII的局限在於只能顯示26個基本拉丁字母、阿拉伯數字和英式標點符號。因此,現在的軟件系統大多采用Unicode,特別是與ASCII向下兼容的UTF-8
對於亞洲國家的文字, 使用的符號就更多了, 漢字就多達10萬左右. 一個字節只能表示256種符號, 肯定是不夠的, 就必須使用多個字節表達一個符號. 比如, 簡體中文常見的編碼方式是GB2312, 使用兩個字節表示一個漢字, 所以理論上最多可以表示256x256=65536個符號.
2. Unicode(萬國碼)
Unicode官網:https://home.unicode.org/
2.1 Unicode的定義
Unicode的范圍為 【0-0x10FFFF】,換算成10進制為【0-1114111】有0-1,114,112個字符,所以100多萬個字符是足以支持世界上的任何語言的
世界上存在着多種編碼方式, 同一個二進制數字可以被解釋成不同的符號. 因此, 要想打開一個文本文件, 就必須知道它的編碼方式, 否則用錯誤的編碼方式解讀, 就會出現亂碼.為什么電子郵件常常出現亂碼?就是因為發信人和收信人使用的編碼方式不一樣.
可以想象, 如果有一種編碼, 將世界上所有的符號都納入其中. 每一個符號都給予一個獨一無二的編碼, 那么亂碼問題就會消失. 這就是Unicode, 就像它的名字都表示的, 這是一種所有符號的編碼.
Unicode也是一種字符編碼方法, 不過它是由國際組織設計, 可以容納全世界所有語言文字的編碼方案. Unicode的學名是"Universal Multiple-Octet Coded Character Set",簡稱為UCS. UCS可以看作是"Unicode Character Set"的縮寫.
Unicode當然是一個很大的集合, 現在的規模可以容納100多萬個符號. 每個符號的編碼都不一樣, 比如, U+0639表示阿拉伯字母Ain, U+0041表示英語的大寫字母A, U+4E2D表示漢字中國的"中". 具體的符號對應表, 可以查詢unicode.org, 或者專門的漢字對應表.
2.2 Unicode的問題
需要注意的是, "Unicode只是一個符號集, 它只規定了符號的二進制代碼, 卻沒有規定這個二進制代碼應該如何存儲".
比如, 漢字"中"的unicode是十六進制數4E2D, 轉換成二進制數足足有15位(100111000101101), 也就是說這個符號的表示至少需要2個字節. 表示其他更大的符號,可能需要3個字節或者4個字節, 甚至更多.
這里就有兩個嚴重的問題, 第一個問題是, 如何才能區別unicode和ascii?計算機怎么知道三個字節表示一個符號, 而不是分別表示三個符號呢?第二個問題是, 我們已經知道,英文字母只用一個字節表示就夠了, 如果unicode統一規定, 每個符號用三個或四個字節表示, 那么每個英文字母前都必然有二到三個字節是0, 這對於存儲來說是極大的浪費,文本文件的大小會因此大出二三倍, 這是無法接受的.
它們造成的結果是:
1) 出現了unicode的多種存儲方式, 也就是說有許多種不同的二進制格式,可以用來表示unicode.
2) unicode在很長一段時間內無法推廣, 直到互聯網的出現
注意:Unicode只是一個符號集,它只規定了各個字符所對應的二進制數,並沒有規定在計算機中如何存儲以及傳輸的問題
2.3 UCS(Unicode的定長字符編碼)【這部分參考鏈接:https://blog.csdn.net/qq_52102933/article/details/126595077】
通用多八位編碼字符集(Universal Multiple-Octet Coded Character Set)也叫通用字符集(Universal Character Set, UCS),是由ISO制定的ISO 10646(或稱ISO/IEC 10646)標准所定義的標准字符集。
通用多八位編碼字符集包括了其他所有字符集。它保證了與其他字符集的雙向兼容,即,如果你將任何文本字符串翻譯到UCS格式,然后再翻譯回原編碼,你不會丟失任何信息。
UCS-2
UCS-2(Universal Character Set coded in 2 octets),是用定長2個字節來表示字符(定長編碼,ASCII碼部分的字符存儲也是2個字節),其取值范圍為 U+0000~U+FFFF。Unicode當前默認的版本是UCS-2,UCS-2 編碼 與 Unicode碼 完全一樣,6w+的字符量已經足以用於全球的主要語言的大多數字符。
可以參考以下截圖:中(4e2d)國(56fd)A(0041)a(0061)
UCS-4
但是Unicode為了能表示更多的文字,還是提供了一個擴展機制(UCS-4,用四個字節表示代碼點,最高位為0,取值范圍為 U+00000000~U+7FFFFFFF),允許表示一百多萬個字符。
比如,英文字母“A”對應的Unicode(十六進制)是U+0041,轉換為十進制是65,轉換為二進制是0100 0001,和ASCII碼一致,只需要一個字節表示。
比如,中文“一”對應的Unicode(十六進制)是U+4E00,轉換為十進制是19968,轉換為二進制是100 1110 0000 0000,這個二進制有15位,需要至少2個字節表示。
具體的符號對應表,可以查詢Unicode官網,也可以查詢專門的漢字對應表,還有字符與Unicode編碼在線轉換。
3. UTF-8
互聯網的普及, 強烈要求出現一種統一的編碼方式. UTF-8就是在互聯網上使用最廣的一種unicode的實現方式. 其他實現方式還包括UTF-16和UTF-32, 不過在互聯網上基本不用.重復一遍, 這里的關系是, UTF-8是Unicode的實現方式之一。
UTF-8最大的一個特點, 就是它是一種變長的編碼方式. 它可以使用1~6個字節表示一個符號, 根據不同的符號而變化字節長度.
對比 | UTF-8 | UTF-16 | UTF-32 | UCS-2 | UCS-4 |
---|---|---|---|---|---|
編碼空間 | 0 ~ 10FFFF | 0 ~ 10FFFF | 0 ~ 10FFFF | 0 ~ FFFF | 0 ~ 7FFFFFFF |
最少編碼字節數 | 1 | 2 | 4 | 2 | 4 |
最多編碼字節數 | 4 | 4 | 4 | 2 | 4 |
是否依賴字節序 | 否 | 是 | 是 | 是 | 是 |
3.1 UTF-8的編碼規則
UTF-8的編碼規則很簡單, 只有兩條:
1) 對於單字節的符號, 字節的第一位設為0, 后面7位為這個符號的unicode碼. 因此對於英語字母, UTF-8編碼和ASCII碼是相同的。
2) 對於n字節的符號(n>1), 第一個字節的前n位都設為1, 第n+1位設為0, 后面字節的前兩位一律設為10. 剩下的沒有提及的二進制位, 全部為這個符號的unicode碼。
下表總結了編碼規則, 字母x表示可用編碼的位.
下面, 還是以漢字"中"為例, 演示如何實現UTF-8編碼.
已知"中"的unicode是4E2D(100111000101101), 根據上表, 可以發現4E2D處在第三行的范圍內(0000 0800 - 0000 FFFF), 因此"中"的UTF-8編碼需要三個字節, 即格式是"1110xxxx 10xxxxxx 10xxxxxx". 然后,從"中"的最后一個二進制位開始, 依次從后向前填入格式中的x, 多出的位補0. 這樣就得到了, "中"的UTF-8編碼是 "11100100 10111000 10101101", 轉換成十六進制就是E4B8AD.
4. Little endian和Big endian
Unicode碼可以采用UCS-2格式直接存儲. 以漢字"中"為例, Unicode碼是4E2D, 需要用兩個字節存儲, 一個字節是4E, 另一個字節是2D. 存儲的時候, 4E在前,2D在后, 就是Big endian方式; 2D在前, 4E在后, 就是Littleendian方式.// Big Endian(4E2D) Little Endian(2D4E)
因此, 第一個字節在前, 就是"大頭方式"(Big endian), 第二個字節在前就是"小頭方式"(Little endian)。
4.1 計算機如何判定是哪一種編碼?(零寬度非換行空格(FEFF)),這個也就BOM
Unicode規范中定義, 每一個文件的最前面分別加入一個表示編碼順序的字符, 這個字符的名字叫做"零寬度非換行空格"(ZERO WIDTH NO-BREAK SPACE), 用FEFF表示. 這正好是兩個字節, 而且FF比FE大1.// Big Endian(FEFF),Little Endian(FFFE)
如果一個文本文件的頭兩個字節是FE FF, 就表示該文件采用大頭方式; 如果頭兩個字節是FF FE, 就表示該文件采用小頭方式。
此處使用Notepad++進行演示
以二進制方式打開效果(插件里有一個HEX-Editor可以查看二進制):
5. Unicode與UTF-8之間的轉換(javascript)