你不知道的 字符集和編碼(編碼字符集與字符集編碼)

2021-06-26 23:42:39 字數 4013 閱讀 6135

我的上篇文章,有朋友提出字符集和編碼的區別,我在此立文和大家討論下

常說的字符集和編碼區別,其實就是編碼字符集和字符集編碼的區別,其實,單單如果只是說字符集,沒有任何編碼的概念的話,那麼字符集其實僅僅是乙個簡單的字元的集合,或者說是乙個抽象的字元的集合,包括文字,符號等等,不參與任何儲存形式,只是存在這麼各種各樣標準的字元的集合

如果僅僅是抽象的字符集,我們是無需拿出討論的,因為沒有任何異議,通俗易懂,而常說的字符集指的編碼字符集,比如常見的 unicode、ascii、gb2312、gbk等,這些我們常稱做為字符集(其實是編碼字符集),這些字符集,比如unicode其實本質上是已經「編碼」過的字符集,即每個字元都有唯一的整數編號,每個字元都有自己特有的編號,同乙個字元在不同編碼字符集中編號也會不同,當然很多編碼字符集都是ascll的超集,所以ascll字符集的編號與很多編碼字符集中編號都一樣,比如英文本母「a」,在ascii及unicode及gb2312中,均是第0×41個字元,說到這裡朋友一定注意到了我上面再描述「 unicode其實本質上是已經「編碼」過的字符集」中的「編碼」二字加了雙引號,我要強調的是這裡的「編碼」並不是真的我下面要說的編碼,這裡只是為每個字元編了乙個對應的編號,但是我們還是習慣專業的稱呼為「編碼字符集」

我們經常說「文章採用的是utf-8編碼方式」

我對於這個編碼方式的意義,個人理解是 將乙個字元的整數編號用乙個什麼二進位制的整數值來對應並在計算機儲存。這和上面說的編碼字符集中的「編碼」千差萬別,這裡我們稱之為「字符集編碼」,即我們常說的編碼

說到這裡,很多人會覺得那麼unicode和utf-8的區別在**?既然上文說到unicode是編碼字符集,那麼utf-8又是什麼?就是常說的編碼?

「文章採用的是utf-8編碼方式」,個人覺得準確的說法是「文章採用的是基於unicode編碼字符集的utf-8的編碼方案」,即

即unicode本身作為編碼字符集沒有任何儲存形式,只是乙個編號和字元對應的表而已,如何在計算機儲存?你可能想到了乾脆直接把編號當作二進位制數值來直接儲存,那麼為什麼不這麼做呢?這也算是一種字符集編碼方案,就是基於unicode編碼字符集的utf-32編碼方案,那麼有沒有更加智慧型一點的編碼方案呢?為什麼會沒有呢?那就是utf-8、utf-16等等,    等等,在我解釋為何要用utf-8編碼方案的時候,我必須說明一件事情:如下

(列表過長,用兩幅圖分別截圖)

上圖有兩個疑問:

1、如果說unicode是編碼字符集,為何會出現在和utf-8這種編碼方案並列的列表中?

2、ascii或者gb2312都是編碼字符集為何也會出現在和utf-8這種編碼方案並列的列表中?

我們假設有兩個猜測:

1、此處的unicode並不是真正的unicode編碼字符集,可能只是一種和unicode編碼字符集關係非常緊密的一種編碼方案

2、ascii或者gb2312(其實就是圖中的default,即作業系統當前的編碼,國內一般為gb2312)是編碼字符集沒有錯,但是對於ascii或者gb2312都只有唯一一種編碼,那麼我稱呼它們為ascii編碼或者gb2312編碼也沒有問題,既然這樣,那我把ascii和gb2312加入和utf-8這種編碼方案並列的列表中也理所當然?

我的兩個假設,很快得到論證

1、在encoding 的元資料看到:

1

2

3

4

5

6

7

//

// 摘要:

//     獲取使用 little-endian 位元組順序的 utf-16 格式的編碼。

//

// 返回結果:

//     使用 little-endian 位元組順序的 utf-16 格式的編碼。

publicstaticencoding unicode

這裡解釋在這裡的unicode其實本質上「獲取使用 little-endian 位元組順序的 utf-16 格式的編碼」,即使基於unicode編碼字符集的utf-16編碼方案,類似的有bigendianunicode(獲取使用 big endian 位元組順序的 utf-16 格式的編碼)

2、一般的ascii或者gb2312,我們可以稱呼為ascii字符集也可以稱呼為ascii編碼,只是意義不同而已,因為對於ascii編碼字符集或者gb2312編碼字符集都只有唯一一種編碼,就是ascii編碼和gb2312編碼,那麼列表中顯示的ascii和gb2312指的不是編碼字符集而是ascii和gb2312的編碼方案,我想正是這種原因,才在很多時候,不管是字符集賦值還是編碼方案賦值都可以直接用gb2312或者ascii,比如:

encoding gb2312 = encoding.getencoding(「gb2312″);

response.contentencoding = gb2312;//編碼

response.charset=」gb2312″;//字符集

總結下的說:

就是unicode是字符集,不是編碼!但是ascii(gb2312)是字符集,這個說法肯定正確,但是我表達為「ascii編碼」也不能說大錯特錯,但是這種說法讓人誤解,如果一定要說那麼就說「ascii編碼字符集的編碼」

如果理解上面兩個假設的論證道理,那麼我們繼續討論之前暫停的話題,即「解釋為何要用utf-8等編碼方案(其他utf編碼方案類似)」

utf-8將很大一部分基於unicode編碼字符集的字元的整數編號作了變換後儲存在計算機中。(引用)以「漢」字為例,「漢」的unicode值為0x6c49,但其編碼為utf-8格式後的值為0xe6b189(注意到變成了三個位元組)。對於utf-16編碼方案,則是對unicode編碼字符集中的前65536個字元編號都不做變換,直接作為計算機儲存時使用的值(對65536以後的字元,仍然要做變換),例如「漢」字的unicode編號為0x6c49,那麼經過utf-16編碼後儲存在計算機上時,它的表示仍為0x6c49,對於utf-32編碼方案,他對所有的unicode字元均不做變換,直接使用編號儲存,只是這種編碼方案太浪費儲存空間(就連1個位元組就可以搞定的英文本元,它都必須使用4個位元組)

既然unicode編碼字符集有如此多的編碼方案,那麼

utf-8,字母數字符號等佔1位元組,漢字佔三位元組

utf-16,對unicode編碼字符集中的前65536個字元都佔兩個位元組

utf-32,全部佔四位元組

如果還有人問:

「unicode編碼每個字元佔幾個位元組」,我們可以理直氣壯的說,第一unicode不是編碼!第二每個字元具體佔多少位元組是要看編碼方案!

很多面試題會問: 1

2

3

string param ="abc阿道夫";

intlength1 = system.text.encoding.unicode.getbytes(param).length;//別忘了這裡的unicode本質是utf-16編碼方案

intlength2 = param.length;

那麼答案就是12和6了

最後,對於gb2312或者ascii編碼字符集的字元的編號就是直接儲存在計算機中的二進位制數,也就是說gb2312和ascii編碼字符集都只有一種編碼方案,因為在gb2312編碼字符集中的ascii字符集部分的編號並沒有變化(即和ascii編碼字符集中的編碼一致),所以gb2312的ascii部分字元存入計算機的二進位制數還是占用1個位元組,而中文字元存入計算機的二進位制數也是該中文字元在gb2312編碼字符集中的編號,該編號一般轉換成二進位制數都佔兩個位元組,這個過程也就變成了所謂的gb2312編碼

如果上面的改為system.text.encoding.default.getbytes(param).length,則值就是9和6了

編碼字符集

gb2312 全稱中國標準第兩千三百一十二條,其中包含亞裔字符集 南韓文字 缺點不包括正體中文,但是台灣還在使用正體中文,於是就有了 gbk gbk 全稱中國標準第兩千三百一十二條擴充套件版本,就包含正體中文 unicode 全稱萬國碼,各個國家的文字都有 utf 8 最通用的,unicode的公升...

編碼字符集與字符集編碼的區別

無論歷史上的ucs還是現如今的unicode,兩者指的都是編碼字符集,而不是字符集編碼。乙個抽象字符集其實就是指字元的集合,例如所有的英文本母是乙個抽象字符集,所有的漢字是乙個抽象字符集,在給乙個抽象字元集合中的每個字元都分配乙個 整數編號之後 注意這個整數並沒有要求大小 這個字符集就有了順序,就成...

MySQL的編碼字符集問題

在專案裡遇到了插入的中文字元變成亂碼的問題,修改了mysql的字符集相關變數卻沒有解決問題,上網找了下,嘗試了各種方法最終解決。修改global的variable set character set database utf8,卻不能解決某個資料庫建好之後,新建的表的character set da...