字符編碼原理
你是否有過在網(wǎng)頁上看到一堆亂碼,完全不知所云的經(jīng)歷?或者你試圖打開一個文檔,結(jié)果看到的都是奇怪的字符?這背后的元兇,很可能是字符編碼。

這聽起來像是一個高深的計算機名詞,但實際上,不管你是學計算機或者不是學計算機的,它關(guān)乎我們每個人。
想象一下,你有沒有經(jīng)歷過這樣一個場景,你在與一個朋友進行通信,但是你們之間的距離很遠,所以你們決定使用一種信號方式。你們都決定:把手舉高意味著“是”或“好的”,把手放低意味著“不是”或“不好”。這就是一個簡單的“編碼”或“約定”:你們賦予特定的手勢以特定的意義。
回到計算機這邊,計算機原生只理解高低電平,只能識別二進制(0和1)。但我們?nèi)祟愂褂玫奈谋臼亲址?、字母、?shù)字和其他符號。所以,我們需要一個方法來告訴計算機:“嘿,當我給你這一串01時,我其實是想表示字母A?!边@就是字符編碼的起源。
1、ASCII:電腦與英文的橋梁
于是,ASCII出現(xiàn)了。這是一個簡單的編碼表,用來告訴計算機:“嘿,當我說‘A’時,你可以用1000001
這串數(shù)字來表示。”就這樣,英文與計算機之間的溝通橋梁被架起。

2、ISO-8859-1:西歐的聲音
但英文并非唯一的語言。歐洲有很多其他的語言和符號。為此,ISO-8859-1出現(xiàn)了,它包含了大部分西歐語言的字符。
3、東方字符與編碼的挑戰(zhàn)
東方的文字千變?nèi)f化,尤其是中文,每一個漢字都是一個小故事。但如何將它們“翻譯”給只懂0和1的計算機呢?
3.1 GB2312、GBK:中文的數(shù)字化嘗試
中國的工程師們沒有退縮。他們創(chuàng)建了GB2312和GBK編碼,試圖用數(shù)字語言告訴計算機每一個漢字的樣子。
3.2 Big5:臺灣與香港的文字編碼
而在臺灣和香港,Big5編碼則擔任這個重要任務。
4、Unicode:全球統(tǒng)一的解決方案
但隨著時間的流逝,人們意識到:我們需要一個全球通用的字符編碼,而不是每個地方都有自己的編碼。這就是Unicode的起源。它像是一個超大的“字典”,試圖涵蓋地球上所有的文字。
4.1 UTF系列:Unicode的實現(xiàn)方式
但是,僅有字典是不夠的。我們還需要一種方法,讓計算機能讀懂這個字典。因此,UTF-8、UTF-16和UTF-32這幾種“翻譯方法”應運而生。
尤其是UTF-8,幾乎成為了互聯(lián)網(wǎng)的通用語言,因為它既能理解簡單的英文字符,也能表達復雜的漢字或其他符號。
5、Unicode和UTF的區(qū)別
這里我重點說一下這兩者的區(qū)別。
理解“UTF”與“Unicode”的區(qū)別是理解字符編碼的關(guān)鍵之一。這兩個詞經(jīng)常被人們混淆,但它們的目標和功能是有所區(qū)別的。
Unicode:
定義:Unicode是一個字符集(CharacterSet)。它定義了每一個字符在計算機中的唯一數(shù)字編號。
目的:為世界上的每一種字符分配一個唯一的編號,無論這個字符是什么語言,什么平臺,什么程序,什么設(shè)備。
例子:在Unicode中,“A”對應的編號是U+0041,而“中”對應的編號是U+4E2D。
注意:Unicode只是定義了字符和編號的映射關(guān)系,但并沒有規(guī)定如何在計算機中存儲這個編號。
UTF (Unicode Transformation Format):
定義:UTF是一系列的字符編碼方案,描述了如何在計算機中存儲和傳輸由Unicode指定的數(shù)字編號。
種類:主要有三種UTF編碼方案:UTF-8、UTF-16和UTF-32。數(shù)字(如“8”,“16”或“32”)代表每個字符使用的位數(shù)的基本單元。例如,UTF-8使用8位(1字節(jié))為基本單元,但某些字符可能會使用多個字節(jié)。
例子:在UTF-8中,“A”的存儲形式是
41
(十六進制),而“中”的存儲形式是E4 B8 AD
(十六進制)。優(yōu)勢:UTF-8尤為重要,因為它是兼容ASCII的,且在互聯(lián)網(wǎng)中廣泛使用。
簡單比喻:
想象Unicode是一本“世界語言詞典”,其中為每個詞(字符)分配了一個唯一的編號。而UTF則是這本詞典的“打印格式”,規(guī)定了如何在紙上(或者在計算機的存儲介質(zhì)中)呈現(xiàn)這些編號。
總之,Unicode定義了字符與數(shù)字之間的關(guān)系,而UTF定義了如何存儲和傳輸這些數(shù)字。
6、UTF-8如何表示中文?
首先明確一下,UTF-8 是 Unicode 的一種可變長度字符編碼。它使用一個到四個字節(jié)表示每個符號,取決于符號在 Unicode 中的編號。對于中文字符,UTF-8 通常使用三個字節(jié)進行編碼。
這是因為中文字符在 Unicode 中的代碼點大于 ASCII,但又小于需要四個字節(jié)編碼的代碼點。
要了解如何表示中文字符,我們可以先了解 UTF-8 的編碼機制:
對于單字節(jié)的符號,字節(jié)的第一位設(shè)為0,后面7位為這個符號的 Unicode 代碼。這和 ASCII 編碼兼容。
對于 n 字節(jié)符號(n>1),第一個字節(jié)的前 n 位都設(shè)為1,第 n+1 位設(shè)為0,后面字節(jié)的前兩位都設(shè)為10。剩下的沒有提到的二進制位,全部為這個符號的 Unicode 代碼。
現(xiàn)在,我們以中文字符“中”為例,來看它是如何被 UTF-8 編碼的:
“中”的 Unicode 代碼點為 U+4E2D。
將這個代碼點從十六進制轉(zhuǎn)為二進制,得到
100111000101101
。根據(jù) UTF-8 的編碼規(guī)則,因為這是一個三字節(jié)的編碼,所以格式是
1110xxxx 10xxxxxx 10xxxxxx
。填入“中”的二進制編碼:
11100100 10111000 10101101
。最終,我們得到的 UTF-8 編碼(以十六進制表示)為:E4 B8 AD。
所以,當你在一個 UTF-8 編碼的文本文件中看到這三個連續(xù)的字節(jié) E4 B8 AD,就知道這代表中文字符“中”。
這種編碼方式允許 UTF-8 同時具有與 ASCII 編碼的兼容性,并能夠表示所有的 Unicode 字符。對于中文字符,它通常使用三個字節(jié),但對于某些特別的字符或表情符號,可能需要四個字節(jié)。
7、為什么還有亂碼?
每次我們在瀏覽器中打開一個網(wǎng)頁,或在計算機上讀取一個文檔,背后都有一套編碼在默默地工作。你可能在某些網(wǎng)頁的底部看到過“UTF-8”或“GBK”這樣的標簽。這其實是告訴計算機:“嘿,這個頁面的文字,請按照這種規(guī)則來讀?!?/span>
所以看完上面的,你可能會問,既然我們有了那么多高科技,為什么還會遇到亂碼問題?
原因有很多,但最常見的是:文件或網(wǎng)頁的原始編碼與我們所使用的軟件或設(shè)備預期的編碼不匹配,比如網(wǎng)頁是用ISO編碼,但是我們是用GBK打開。
這就像我們試圖用法語讀英文一樣,結(jié)果自然是不對勁的。
隨著當前機器學習、ChatGPT類似AI的興起,我們也可以期待一下,在不久的將來,你的計算機或手機或許能夠自動檢測并修復亂碼問題,那么【手持兩把錕斤拷,口中疾呼燙燙燙】也將成為歷史!??!
