精仿手表 Golang中的Unicode與字符串示例詳解

ql009com006 高仿手表評論閱讀模式
摘要今天看到一個面試問題:Unicode 和 UTF-8 有何區(qū)別?我的簡單理解就是Unicode 是字符集,而UTF-8是編碼集/方式,之前在HTML字符集里總結過相關問題。

頂級復刻手表高仿手表咨詢wx:AW445890

①UTF-8是Unicode編碼的一種編碼方法。

原因:節(jié)省流量和硬盤

不過:一個漢字在UTF-8編碼的情況下可能需要三個字節(jié),而使用gbk兩個字節(jié)就夠了,所以有時為了節(jié)省流量和硬盤,面對中文世界時,也使用gbk或gbk2312編碼

②Unicode是包含所有字符的字符集,解決了世界各地使用不同編碼方式的尷尬,讓我們能夠更好地溝通。 UTF-8是為了解決Unicode的內(nèi)存問題而對Unicode進行重新編碼的一種編碼方法。

③可以這樣理解:

字符串是由字符組成的,字符在計算機硬件中以二進制形式存儲。 這種二進制形式就是編碼。 如果直接使用“字符串??字符??二進制表示(編碼)”,會增加不同類型編碼之間轉換的復雜度。

因此,引入了一個抽象層,“字符串??字符??存儲獨立表示??二進制表示(編碼)”。 這樣,字符就可以用與存儲無關的形式來表示,并且在不同編碼之間進行轉換時,可以先轉換到這個抽象層,然后再轉換為其他編碼形式。 這里,unicode是“與存儲無關的表示”,utf-8是“二進制表示”。

④計算機只能存儲101010這樣的二進制數(shù)據(jù),那么頁面上顯示的字符是如何顯示的呢?

1:字符集(Charset)

charset = char + set,char是字符,set是集合,charset是字符的集合。 字符集是指這種編碼方式所涵蓋的字符。 每個字符都有一個數(shù)字序列。

2:編碼

編碼方法是指如何將字符編碼為二進制字節(jié)順序,反之亦然。 也就是說,您會得到一個數(shù)字序列號、需要編碼成多少字節(jié)、字節(jié)順序或其他特殊規(guī)則。

三:字體(Font)

根據(jù)數(shù)字序號調(diào)用字體中存儲的字體,即可顯示在頁面上。 因此,如果要顯示一個字符,它的顯示方式取決于字體文件。

綜上所述,Unicode只是一種字符集,而不是一種編碼。 UTF-8是Unicode字符集的一種編碼方法。 其他還有UTF-16、UTF-32等,隨著字符集和編碼方式的不同,如果系統(tǒng)字體沒有這個字符,就不會顯示。

【擴張】

(1) 字符串和編碼

計算機只能處理數(shù)字。 如果要處理文本,必須先將文本轉換為數(shù)字后再進行處理。 最早的計算機是使用 8 位作為一個字節(jié)來設計的。 因此,一個字節(jié)可以表示的最大整數(shù)是255(二進制11111111=十進制255)。 如果要表示更大的整數(shù),則必須使用更多字節(jié)。 例如,兩個字節(jié)可以表示的最大整數(shù)是65535,4個字節(jié)可以表示的最大整數(shù)是4294967295。

由于計算機是美國人發(fā)明的,最初被編碼進計算機的只有127個字符,即大小寫英文字母、數(shù)字和一些符號。 該編碼表稱為 ASCII 編碼。 例如,大寫字母 A 的編碼為 65 ,小寫字母 z 的編碼為 122 。

但對于處理中文來說,一個字節(jié)顯然是不夠的。 至少需要兩個字節(jié),且不能與ASCII編碼沖突。 因此,我國制定了GB2312編碼來對中文進行編碼。

你可以想象,世界上有數(shù)百種語言。 日本將日語編譯為Shift_JIS,韓國將韓語編譯為Euc-kr。 每個國家都有自己的標準,難免會發(fā)生沖突。 結果就是在多種語言的混合文本顯示時可能會出現(xiàn)亂碼。

因此,Unicode應運而生。 Unicode將所有語言統(tǒng)一為一組編碼,因此不會再出現(xiàn)亂碼問題。

Unicode 標準在不斷發(fā)展,但最常用的是使用兩個字節(jié)來表示一個字符(如果要使用非常罕見的字符,則需要 4 個字節(jié))。 現(xiàn)代操作系統(tǒng)和大多數(shù)編程語言都直接支持Unicode。

現(xiàn)在,我們來看看ASCII編碼和Unicode編碼的區(qū)別:ASCII編碼是1個字節(jié),而Unicode編碼通常是2個字節(jié)。

字母A用ASCII編碼為十進制為65,二進制為01000001;

字符0的ASCII編碼十進制為48,二進制為00110000。 注意字符“0”與整數(shù)0不同;

漢字已經(jīng)超出了ASCII編碼的范圍。 Unicode 編碼為十進制 20013,二進制為 01101。

你可以猜測,如果使用Unicode編碼進行ASCII編碼,只需要在前面加0即可。 因此,A的Unicode編碼為00001。

新的問題又出現(xiàn)了:如果統(tǒng)一成Unicode編碼,亂碼問題就消失了。 但是,如果你寫的文本基本上都是英文,那么Unicode編碼需要比ASCII編碼多一倍的存儲空間,這在存儲和傳輸方面是非常不經(jīng)濟的。

因此,本著節(jié)約的精神,將Unicode編碼轉換為“可變長度編碼”的UTF-8編碼出現(xiàn)了。 UTF-8編碼將一個Unicode字符根據(jù)不同的數(shù)字大小編碼為1-6個字節(jié)。 常用的英文字母編碼為1個字節(jié),漢字通常為3個字節(jié)。 只有非常罕見的字符才會被編碼。 編碼為4-6字節(jié)。 如果要傳輸?shù)奈谋景罅坑⑽淖址梢酝ㄟ^將其編碼為 UTF-8 來節(jié)省空間:

01000001

00001

01000001

中間

01101

11

從上表中我們還可以發(fā)現(xiàn)UTF-8編碼還有一個額外的好處,那就是ASCII編碼實際上可以看成是UTF-8編碼的一部分。 因此,大量僅支持 ASCII 編碼的歷史遺留軟件可以采用 UTF-8 進行編碼。 繼續(xù)在 8 編碼下工作。

明確了 ASCII、Unicode 和 UTF-8 之間的關系后,我們可以總結一下目前計算機系統(tǒng)中常見的字符編碼方式:

計算機內(nèi)存中統(tǒng)一使用Unicode編碼。 當需要保存到硬盤或傳輸時,會轉換為UTF-8編碼。

使用記事本進行編輯時,從文件中讀取的UTF-8字符會轉換為Unicode字符并存儲在內(nèi)存中。 編輯完成后,保存時將Unicode轉換為UTF-8保存到文件中:

瀏覽網(wǎng)頁時,服務器會將動態(tài)生成的Unicode內(nèi)容轉換為UTF-8,然后傳輸給瀏覽器:

所以你在很多網(wǎng)頁的源代碼上看到類似的信息,說明該網(wǎng)頁使用了UTF-8編碼。

(2) ASCII、Unicode、UTF-8在字符編碼方面的區(qū)別

1.ASCII碼

我們知道,在計算機內(nèi)部,所有信息最終都表示為二進制字符串。 每個二進制位(bit)都有兩種狀態(tài):0和1,所以8個二進制位可以組合成256種狀態(tài),稱為一個字節(jié)。 也就是說,一個字節(jié)總共可以表示256種不同的狀態(tài),每種狀態(tài)對應一個符號,即從00000000到11111111共256個符號。

20世紀60年代,美國制定了一套字符編碼,統(tǒng)一了英文字符和二進制位的關系。 這稱為 ASCII,至今仍在使用。

ASCII碼總共指定了128種字符編碼。 例如,空格“SPACE”為32(二進制00100000),大寫字母A為65(二進制01000001)。 這128個符號(包括32個無法打印的控制符號)只占用一個字節(jié)的最后7位,第一位統(tǒng)一設置為0。

2.非ASCII編碼

用128個符號對英語進行編碼就足夠了,但要表示其他語言,128個符號是不夠的。 例如,在法語中,如果字母上面有注音符號,則無法用 ASCII 碼表示。 于是,一些歐洲國家決定利用字節(jié)中空閑的最高位來編碼新的符號。 例如,法語中 é 的編碼為 130(二進制 10000010)。 因此,這些歐洲國家使用的編碼系統(tǒng)最多可以表示 256 個符號。

然而,這里出現(xiàn)了一個新問題。 不同的國家有不同的字母,所以即使它們都使用256符號編碼,它們所代表的字母也是不同的。 例如,130 在法語編碼中代表 é,在希伯來語編碼中代表字母 Gimel (?),在俄語編碼中代表另一個符號。 但不管怎樣,在所有這些編碼方式中,0--127所代表的符號都是一樣的,唯一的區(qū)別就是128--255這部分。

至于亞洲國家的文字,使用的符號就更多了,漢字多達十萬個。 一個字節(jié)只能表示256個符號,這肯定是不夠的。 必須使用多個字節(jié)來表達一個符號。 比如簡體中文常見的編碼方式是GB2312,它用兩個字節(jié)來表示一個漢字,所以理論上最多可以表示256x256=65536個符號。

中文編碼的問題需要專門一篇文章來討論,本筆記不涉及。 這里只是指出,雖然用多個字節(jié)來表示一個符號,但是GB類的漢字編碼與后面介紹的Unicode和UTF-8無關。

3.統(tǒng)一碼

世界上有很多種編碼方式,同一個二進制數(shù)可以解釋成不同的符號。 因此,如果要打開一個文本文件,就必須知道它的編碼方式,否則如果使用錯誤的編碼方式來解釋,就會出現(xiàn)亂碼。 為什么郵件經(jīng)常出現(xiàn)亂碼? 這是因為發(fā)送者和接收者使用不同的編碼方法。

可以想象,如果有一個代碼,包含了世界上所有的符號。 每個符號都被賦予唯一的代碼,因此亂碼問題就會消失。 顧名思義,這就是 Unicode,所有符號的編碼。

Unicode 當然是一個很大的集合,目前的大小可以容納超過 100 萬個符號。 每個符號的編碼是不同的。 例如,U+0639代表阿拉伯字母Ain,U+0041代表英文大寫字母A,U+4E25代表漢字“yan”。 您可以查看特定符號對應表,或者特殊漢字對應表。

4. 統(tǒng)一碼問題

需要注意的是,Unicode 只是一個符號集。 它只指定了符號的二進制代碼,但沒有指定這個二進制代碼應該如何存儲。

例如,漢字“嚴格”的unicode是十六進制數(shù)4E25,轉換成15位的二進制數(shù)(0101),這意味著這個符號的表示至少需要2個字節(jié)。 表示其他較大的符號可能需要 3 個字節(jié)或 4 個字節(jié),甚至更多。

這里有兩個嚴重的問題

第一個問題是,如何區(qū)分 Unicode 和 ASCII? 計算機如何知道三個字節(jié)代表一個符號,而不是三個單獨的符號?

第二個問題是我們已經(jīng)知道只有一個字節(jié)就足以表示英文字母。 如果Unicode統(tǒng)一規(guī)定每個符號由三個或四個字節(jié)表示,那么每個英文字母前面必須有兩個字符。 三個字節(jié)為0,對存儲來說是巨大的浪費,而且文本文件的大小會變大兩三倍,這是不可接受的。

他們的結果是: 1)Unicode的多種存儲方式出現(xiàn)了,這意味著有很多種不同的二進制格式可以用來表示Unicode。 2)Unicode在很長一段時間內(nèi)無法得到推廣,直到互聯(lián)網(wǎng)的出現(xiàn)。

5.UTF-8

互聯(lián)網(wǎng)的普及強烈要求統(tǒng)一編碼方法的出現(xiàn)。 UTF-8 是 Internet 上使用最廣泛的 Unicode 實現(xiàn)。 其他實現(xiàn)還有UTF-16(字符用兩個字節(jié)或四個字節(jié)表示)和UTF-32(字符用四個字節(jié)表示),但在互聯(lián)網(wǎng)上基本不使用。 同樣,這里的關系是UTF-8是Unicode的實現(xiàn)之一。

UTF-8最大的特點之一是它是一種可變長度的編碼方法。 它可以用1~4個字節(jié)來表示一個符號,字節(jié)長度根據(jù)不同的符號而不同。

UTF-8的編碼規(guī)則很簡單,只有兩條:

(1) 對于單字節(jié)符號,該字節(jié)的第一位設置為0,接下來的7位是該符號的Unicode碼。 所以對于英文字母來說,UTF-8編碼和ASCII碼是一樣的。

(2) 對于n字節(jié)符號(n>1),第一個字節(jié)的前n位設置為1,第n+1位設置為0,后面字節(jié)的前兩位設置為10其余未提及的二進制位均為該符號的unicode編碼。

下表總結了編碼規(guī)則,其中字母 x 表示可用的編碼位。

Unicode 符號范圍 | UTF-8編碼方式

(十六進制)| (二進制)

------------------+---------------------------------------- --- ----------------

0 007F | 0xxxxxxx

0 07FF | 0 07FF 110xxxxx 10xxxxxx

0 FFFF | 0 1110xxxx 10xxxxxx 10xxxxxx

0 FFFF | 0 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

接下來我們以漢字“嚴”為例,演示如何實現(xiàn)UTF-8編碼。

已知“strict”的unicode是4E25(0101)。 根據(jù)上表可以發(fā)現(xiàn)4E25在第三行(0 FFFF)范圍內(nèi)。 因此,“嚴格”的UTF-8編碼需要三個字節(jié),即格式為“1110xxxx 10xxxxxx 10xxxxxx”。 然后,從“strict”的最后一位二進制數(shù)開始,從后向前填寫格式中的x,多余的位補0。這樣,我們就得到“strict”的UTF-8編碼為“11”,轉換為十六進制后為E4B8A5。

文章末尾固定信息

我的微信
這是我的微信掃一掃
weinxin
我的微信
我的微信公眾號
我的微信公眾號掃一掃
weinxin
我的公眾號
 
ql009com006
  • 本文由 ql009com006 發(fā)表于 2023年10月4日 09:00:34
匿名

發(fā)表評論

匿名網(wǎng)友
:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:
確定