1.3 字元集與亂碼
了解0 和1 的實體信号來源及數值表示方式後,如何将0 和1 表示成我們看到的文字呢?從26 個英文字母說起,大小寫共52 個,加上10 個數字達到62 個,考慮到還有特殊字元(如:! @ # $ % ^ & * { } | 等)和不可見的控制字元,必然超過64 個,這又該如何表示呢?注意這裡特别提到了“64”,因為它的特殊性,即2 的6 次方。使用剛才的0 與1 組合,至少是7 組連續的信号量。計算機在誕生之初對于存儲和傳輸媒體實在沒有什麼信心,是以預留了一個bit(位)用于奇偶校驗,這就是1 個Byte(位元組)由8 個bit 組成的來曆,也就是ASCII 碼。
在ASCII 碼中,有兩個特殊的控制字元10 和13,前者是LF 即“\n”,後者是CR 即“\r”,在編碼過程中,代碼的換行雖然是預設不可見的,但在不同的作業系統中,表示方式是不一樣的。在UNIX 系統中,換行使用換行符“\n”;在Windows 系統中,換行使用“\r\n”;在舊版macOS 中,換行使用回車符“\r”,在新版macOS 中使用與UNIX 系統相同的換行方式。如圖1-7 所示,目前編碼環境使用換行方式是LF,這也是推薦的換行方式,避免出現源碼在不同作業系統中換行顯示不同的情況。

圖1-7 不同作業系統的換行方式
再說漢字的字元集表示,首先漢字的個數遠遠超過英文字元的個數。畢竟ASCII碼先入為主,必須在它基礎上繼續編碼,也必須想辦法和它相容。一個位元組隻能表示128 個字元,是以采用雙位元組進行編碼。早期使用的标準GB2312 收錄了6763 個常用漢字。而GBK(K 是拼音kuò 的首字母,是擴充的意思)支援繁體,相容GB2312。而後來的GB18030 是國家标準,在技術上是GBK 的超集并與之相容。1994 年正式公布的Unicode,為每種語言中的每個字元都設定了唯一編碼,以滿足跨語言的交流,分為編碼方式和實作方式。實作Unicode 的編碼格式有三種:UTF-8、UTF-16、UTF-32,UTF(Unicode Transformation Format)即Unicode 字元集轉換格式,可以了解為對Unicode 的壓縮方式。根據二八原則,常用文字隻占文字總數的20% 左右。其中,UTF-8 是一種以位元組為機關,針對Unicode 的可變長度字元編碼,用1 ~ 6 個位元組對Unicode 字元進行編碼壓縮,目的是用較少的位元組表示最常用的字元。此規則能有效地降低資料存儲和傳輸成本。
在日常開發中,字元集如果不相容則會造成亂碼。淘寶以前的系統都是GBK編碼,而國際站使用的是UTF-8,在互相檢視源碼時,使用UTF-8 的IDE 環境打開GBK 源碼,中文注釋基本上都是不可讀的亂碼。亂碼的出現場景并不止于編碼環境中,還有網頁展示、文本轉換、檔案讀取等。資料流從底層資料庫到應用層,到Web 伺服器,再到用戶端顯示,每位開發工程師都會碰到字元亂碼的問題,排查起來是一個比較長的鍊路。資料庫是存儲字元之源,在不同層次上都能夠設定獨立的字元集,如伺服器級别、schema 級别、表級别甚至列級别。為了減少麻煩,所有情況下的字元集設定最好是一緻的。