字元集和編碼
我們在實際開發中, 經常需要處理文本資訊, 組成文本的單元我們稱之為字元
計算機隻能處理0和1, 不能直接處理這些字元, 比如說對字元的讀取和存儲
為了解決這個問題, 我們可以建立一個數字與字元的關聯關系, 比如說使用97 -> a, 98 -> b, 99 -> c…依據數字可以查詢對應字元, 依據字元可以查詢對應數字
這樣我們需要處理字元的時候, 就可以先查詢這個映射, 找到字元對應的數字, 然後把這個數字轉換成二進制存儲即可, 讀取的時候亦然
- 字元集: 為每一個字元配置設定一個唯一的數字, 這個數字可以稱之為碼點
- 編碼規則: 把碼點轉換為位元組序列的規則
新的問題
計算機最早是美國發明的, 是以一開始隻需要處理英文的字元就可以了, 也就是ascii字元集. 後來計算機越來越普及, 更多的國家開始使用計算機, 這個時候就需要處理更多的字元, 比如說中文字元, 日韓字元…由于ascii字元集不支援, 是以各個國家也産生了許多支援更多字元的字元集, 比如說支援簡體中文的gb2312字元集, 支援簡體中文、繁體中文和日韓字元的gbk字元集…
多個字元集的問題:
- 維護起來十分複雜, 對于相同的字元, 多個字元集可能重複維護
- 不同字元集對同一個字元配置設定的碼點可能不一樣, 這樣就導緻編碼和解碼必須使用相同的字元集, 不然可能會出現亂碼
unicode字元集和utf-8編碼
unicode字元集
為了解決上述多個字元集的問題, 我們需要一個維護所有字元, 統一的字元集, 我們稱之為unicode字元集. uniocde14.0版本, 一共收錄了144697個字元
編碼規則
unicode解決了字元集統一的問題, 接下來還需要制定相應的編碼規則
定長編碼
最簡單粗暴的編碼規則, 所有碼點都使用相同長度的位元組來表示, 比如說現在已知的字元數量大概14W多, 可以使用三個位元組來表示(0 ~ 16777216)
優點: 編碼簡單
缺點: 不夠節約空間, 隻需要使用一個位元組和兩個位元組表示的字元也使用了三個位元組來表示
變長編碼
針對不同範圍的碼點, 使用不同長度的位元組序列來表示
utf-8就是一種變長編碼
位元組 | 格式 | 實際編碼位 | 碼點範圍 |
1位元組 | 0xxxxxxx | 7 | 0 ~ 127 |
2位元組 | 110xxxxx 10xxxxxx | 11 | 128 ~ 2047 |
3位元組 | 1110xxxx 10xxxxxx 10xxxxxx | 16 | 2048 ~ 65535 |
4位元組 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 21 | 65536 ~ 2097151 |
utf-8編碼規則, 是一種字首編碼規則, 每一個位元組都是由标志位 + 實際編碼位組成, 第一個開始位元組的高位1的個數表示這個編碼占用了幾個位元組, 隻占用一個位元組的時候比較特殊, 使用0作為高位标志位
為什麼占用多個位元組時, 除了第一個開始位元組外, 後續的位元組也需要10作為字首标志位?
- 後續位元組使用10作為字首标志位, 标志這個位元組不能作為一個開始位元組, 也是為了解決和開始位元組的字首标志位沖突, 實際上是為了解碼服務
- 這樣做可以把開始位元組和非開始的位元組區分開, 可以對utf-8編碼進行校驗, 如果一個開始位元組後的後續位元組數和開始位元組字首标志位中的位元組數不符合, 那麼校驗失敗