字符集和字符編碼
字符集(CCS: Coded Character Set):
就是一個表格,表示每個字符對應數字(通常用16進製表示),比如unicode字符集中,數字1對應的就是U+00031,字母a對應的就是U+00061。
字符編碼(CEF:Character Encoding Form):
因為計算機只認識0和1,所以計算機在存儲字母a(U+00031)的時候,不能直接存儲。所以就需要編碼將字母a轉換成01表示形式。對於unicode字符,utf8就是它的編碼方案(如何utf8轉換成01表示下文介紹)。
字符:
字符簡單理解就是人類能(容易)看懂得符號。
比如對於漢字嚴,機器存儲的是11100100 10111000 10100101,人類根本看不懂。轉換成unicode表示方法是U+4E25,依然看不懂。
人類只能看懂嚴這個字符,三者之間的關係如下:
字符串到保存文件過程如下:
UTF-8編碼
嚴這個字的unicode碼是U+4E25(對應的二進制數字是100111000100101),而utf8編碼之後是11100100 10111000 10100101,是不是很奇怪?兩個二進制完全不一樣,是因為utf8有一套編碼規則。
UTF-8編碼規則
utf8 最大的一個特點,就是它是一種可變長的編碼方式。它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度。
utf8 的編碼規則很簡單,只有二條:
- 對於單字節的符號,字節的第一位設為
0,後面7位為這個符號的 Unicode 碼。因此對於英語字母,utf8編碼和ASCII碼是相同的。 - 對於
n字節的符號(n > 1),第一個字節的前n位都設為1,第n + 1位設為0,後面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的Unicode碼。
下表總結了編碼規則,字母x表示可用編碼的位。
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
嚴字的Unicode編碼是4E25處於0000 0800 - 0000 FFFF這個範圍裏面,所以需要三個字節表示。
哇塞,原來是這樣
utf8和utf8mb4
utf8mb4只是mysql特有的概念,原因是mysql在5.5.3之前,Unicode收錄的字符還不是很多,(最大)3個字節足夠存儲,所以那時的mysql把utf8(alias of "utf8mb3")存儲也設計為3字節存儲。後來Unicode收錄的字符更多了,擴張到4字節了(比如表情😁)。
MySQL也在5.5.3版本之後增加了這個utf8mb4的編碼,mb4就是most bytes 4的意思,專門用來兼容四字節的Unicode。
MySQL官方網站也解釋了utf8mb3和utf8mb4之間的關係。[](https://dev.mysql.com/doc/ref...https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb4.html
[](https://dev.mysql.com/doc/ref...https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html
總結
Unicode是字符集,是符合和碼點的映射表utf8是Unicode的一種最常見的字符編碼方式(還有utf16、utf32)mysql中utf8實際上是utf8mb3(最大存儲3字節),utf8mb4最大可以存儲4字節(大部分表情都要佔用4字節,所以需要選擇utf8mb4)