「字符集」和「編碼」等幾個層次的概念被徹底分離且模塊化的這樣一個模型,其實是 Unicode 時代才得到廣泛認同的。而對于 ASCII、GB2312、Big5 之類的遺留(legacy)方案,其字符集及其編碼的關系基本是鎖定的,所以常常用「字符編碼」(character encoding)、「代碼頁」(code page)等概念來統稱它們那樣從字符到編碼字節流的整體方案。比如 ASCII 本身就既是字符集又是編碼方案。 1、字符集
字符集:字符集(character set)定義了字符和二進制的對應關系,為每個字符分配了唯一的編號。
可以將字符集理解成一個很大的表格,它列出了所有字符和二進制的對應關系,計算機顯示文字或者存儲文字,就是一個查表的過程。
2、字符編碼
字符編碼:而字符編碼(character encoding)規定了如何將字符的編號存儲到計算機中。為了區分一個字符到底使用了幾個字節,就不能將字符的編號直接存儲到計算機中,字符編號在存儲之前必須要經過轉換,在讀取時還要再逆向轉換一次,這套轉換方案就叫做字符編碼。
3、字符集vs字符編碼
4、常見字符集
字符編碼 | 說明 |
ASCII | 這套編碼是美國人給自己設計的,迄今為止共收錄了 128 個字符 |
ISO/ IEC 8859 | 歐洲字符集,支持丹麥語、荷蘭語、德語、意大利語、拉丁語、挪威語、葡萄牙語、西班牙語,瑞典語等,1987 年首次發布。ASCII 編碼只包含了基本的拉丁字母,沒有包含歐洲很多國家所用到的一些擴展的拉丁字母,比如一些重音字母,帶音標的字母等,ISO/IEC 8859 主要是在 ASCII 的基礎上增加了這些衍生的拉丁字母。 |
Shift_Jis | 日語字符集,包含了全角及半角拉丁字母、平假名、片假名、符號及日語漢字,1978 年首次發布。 |
Big5 | 繁體中文字符集,1984 年發布,通行于臺灣、香港等地區,收錄了 13053 個中文字、408 個普通字符以及 33 個控制字符。 |
GB2312 | 簡體中文字符集,1980 年發布,共收錄了 6763 個漢字,其中一級漢字 3755 個,二級漢字3008 個;同時收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西里爾字母在內的 682 個字符。 |
GBK | 中文字符集,是在 GB2312 的基礎上進行的擴展,1995 年發布。GBK 共收錄了 21886 個漢字和圖形符號,包括 GB2312 中的全部漢字、非漢字符號,以及BIG5 中的全部繁體字,還有一些生僻字。 |
GB18030 | 中文字符集,是對 GBK 和 GB2312 的又一次擴展,2000 年發布。GB18030 共收錄 70244 個漢字,支持中國國內少數民族的文字,以及日語韓語中的漢字。 |
ASCII (American Standard Code for Information Interchange):美國信息交換標準代碼。
看這個名字就知道,這套編碼是美國人給自己設計的,他們并沒有考慮歐洲那些擴展的拉丁字母,也沒有考慮韓語和日語,我大中華幾萬個漢字更是不可能被重視。
ASCII 的標準版本于 1967 年第一次發布,最后一次更新則是在 1986 年,**迄今為止共收錄了 128 個字符**,包含了基本的拉丁字母(英文字母)、阿拉伯數字(也就是 1234567890)、標點符號(,.!等)、特殊符號(@#$%^&等)以及一些具有控制功能的字符(往往不會顯示出來)。
在 ASCII 編碼中,大寫字母、小寫字母和阿拉伯數字都是**連續分布的**(見下表),這給程序設計帶來了很大的方便。例如要判斷一個字符是否是大寫字母,就可以判斷該字符的 ASCII 編碼值是否在 65~90 的范圍內。
ASCII 編碼
標準 ASCII 編碼共收錄了 128 個字符,其中包含了 33 個控制字符(具有某些特殊功能但是無法顯示的字符)和95 個可顯示字符。
(完整的可以去我的博客看)
GB2312 --> GBK --> GB18030 是中文編碼的三套方案,出現的時間從早到晚,收錄的字符數目依次增加,并且向下兼容。
GB2312 和 GBK 收錄的字符數目較少,用 1~2 個字節存儲;
GB18030 收錄的字符最多,用 1、 2、4 個字節存儲。
1、GB2312 和 GBK字符集
從整體上講,GB2312 和 GBK 的編碼方式一致,具體為:
1.1、對于 ASCII 字符,使用一個字節存儲,并且該字節的最高位是 0,這和 ASCII 編碼是一致的,所以說 GB2312 完全兼容 ASCII。
1.2、對于中國的字符,使用兩個字節存儲,并且規定每個字節的最高位都是 1
例如對于字母 A,它在內存中存儲為 01000001;對于漢字中,它在內存中存儲為 11010110 11010000。由于單字節和雙字節的最高位不一樣,所以字符處理軟件很容易區分一個字符到底用了幾個字節。
2、GB18030 字符集
GB18030 為了容納更多的字符,并且要區分兩個字節和四個字節,所以修改了編碼方案,具體為:
1、對于 ASCII 字符,使用一個字節存儲,并且該字節的最高位是 0,這和 ASCII、GB2312,GBK 編碼是一致的。
2、對于常用的中文字符,使用兩個字節存儲,并且規定第一個字節的最高位是 1,第二個字節的高位最多只能有一個連續的 0(第二個字節的最高位可以是 1 也可以是 0,但是當它是 0 時,次高位就不能是 0 了)。注意對比 GB2312 和 GBK,它們要求兩個字節的最高位為都必須為 1。
3、對于罕見的字符,使用四個字節存儲,并且規定第一個和第三個字節的最高位是 1,第二個和第四個字節的高位必須有兩個連續的 0
字符處理軟件在處理文本時,從左往右依次掃描每個字節:
1,如果遇到的字節的最高位是 0,那么就會斷定該字符只占用了一個字節;
2,如果遇到的字節的最高位是 1,那么該字符可能占用了兩個字節,也可能占用了四個字節,不能妄下斷論,所以還要繼續往后掃描:
3,如果第二個字節的高位有兩個連續的 0,那么就會斷定該字符占用了四個字節;
4,如果第二個字節的高位沒有連續的 0,那么就會斷定該字符占用了兩個字節。
先寫這么多吧,后面博客會再進一步的說下數據在里面的存儲分區。
1、Unicode 字符集
ASCII、GB2312、GBK、Shift_Jis、ISO/IEC 8859 等地區編碼都是各個國家為了自己的語言文化開發的,不具有通用性,在一種編碼下開發的軟件或者編寫的文檔,拿到另一種編碼下就會失效,必須提前使用程序轉碼,非常麻煩。
人們迫切希望有一種編碼能夠統一世界各地的字符,計算機只要安裝了這一種字編碼,就能支持使用世界上所有的文字,再也不會出現亂碼,再也不需要轉碼了,這對計算機的數據傳遞來說是多么的方便呀!
就在這種呼吁下,Unicode 誕生了。Unicode 也稱為統一碼、萬國碼;看名字就知道,Unicode 希望統一所有國家的字符編碼。
Unicode 于 1994 年正式公布第一個版本,現在的規??梢匀菁{ 100 多萬個符號,是一個很大的集合。
有興趣的讀取可以轉到 [
https://unicode-table.com/cn/](https://unicode-table.com/cn/) 查看 Unicode 包含的所有字符,以及各個國家的字符是如何分布的。
> Windows、Linux、Mac OS 等常見操作系統都已經從底層(內核層面)開始支持 Unicode,大部分的網頁和軟件也使用 Unicode,Unicode 是大勢所趨。
>有的字符集在制定時就考慮到了編碼的問題,是和編碼結合在一起的,例如 ASCII、GB2312、GBK、BIG5 等,所以無論稱作字符集還是字符編碼都無所謂,也不好區分兩者的概念。而有的字符集只管制定字符的編號,至于怎么存儲,那是字符編碼的事情,Unicode 就是一個典型的例子,它只是定義了全球文字的唯一編號,我們還需要 UTF-8、UTF-16、UTF-32 這幾種編碼方案將 Unicode 存儲到計算機中
2、UTF
UTF 是 Unicode Transformation Format 的縮寫,意思是“Unicode 轉換格式”,后面的數字表明至少使用多少個比特位(Bit)來存儲字符。
UTF-8:一種變長的編碼方案,使用 1~6 個字節來存儲;
UTF-32:一種固定長度的編碼方案,不管字符編號大小,始終使用 4 個字節來存儲;
UTF-16:介于 UTF-8 和 UTF-32 之間,使用 2 個或者 4 個字節來存儲,長度既固定又可變。
2.1、UTF8
UTF-8 的編碼規則很簡單:
如果只有一個字節,那么最高的比特位為 0,這樣可以兼容 ASCII;
如果有多個字節,那么第一個字節從最高位開始,連續有幾個比特位的值為 1,就使用幾個字節編碼,剩下的字節均以 10 開頭。
具體的表現形式為:
0xxxxxxx:單字節編碼形式,這和 ASCII 編碼完全一樣,因此 UTF-8 是兼容 ASCII 的;
110xxxxx 10xxxxxx:雙字節編碼形式(第一個字節有兩個連續的 1);
1110xxxx 10xxxxxx 10xxxxxx:三字節編碼形式(第一個字節有三個連續的 1);
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字節編碼形式(第一個字節有四個連續的 1)。
xxx 就用來存儲 Unicode 中的字符編號。
下面是一些字符的 UTF-8 編碼實例(綠色部分表示本來的 Unicode 編號):
2.2、UTF32
UTF-32 是固定長度的編碼,始終占用 4 個字節,足以容納所有的 Unicode 字符,所以直接存儲 Unicode 編號即可,不需要任何編碼轉換。
2.3、UTF16
UFT-16 使用 2 個或者 4 個字節來存儲。
對于 Unicode 編號范圍在 0 ~ FFFF 之間的字符,UTF-16 使用兩個字節存儲,并且直接存儲 Unicode 編號,不用進行編碼轉換,這跟 UTF-32 非常類似。
對于 Unicode 編號范圍在 10000~10FFFF 之間的字符,UTF-16 使用四個字節存儲,具體來說就是:將字符編號的所有比特位分成兩部分,較高的一些比特位用一個值介于 D800~DBFF 之間的雙字節存儲,較低的一些比特位(剩下的比特位)用一個值介于 DC00~DFFF 之間的雙字節存儲。
3、對比以上三種編碼方案
只有 UTF-8 兼容 ASCII,UTF-32 和 UTF-16 都不兼容 ASCII,因為它們沒有單字節編碼。
1、 UTF-8 使用盡量少的字節來存儲一個字符,不但能夠節省存儲空間,而且在網絡傳輸時也能節省流量,所以很多純文本類型的文件(例如各種編程語言的源文件、各種日志文件和配置文件等)以及絕大多數的網頁(例如百度、新浪、163 等)都采用 UTF-8 編碼。
UTF-8 的缺點是效率低,不但在存儲和讀取時都要經過轉換,而且在處理字符串時也非常麻煩。例如,要在一個 UTF-8 編碼的字符串中找到第 10 個字符,就得從頭開始一個一個地檢索字符,這是一個很耗時的過程,因為 UTF-8 編碼的字符串中每個字符占用的字節數不一樣,如果不從頭遍歷每個字符,就不知道第 10 個字符位
于第幾個字節處,就無法定位。
2、UTF-32 是“以空間換效率”,正好彌補了 UTF-8 的缺點,UTF-32 的優勢就是效率高:UTF-32 在存儲和讀取字符時不需要任何轉換,在處理字符串時也能最快速地定位字符。
例如,在一個 UTF-32 編碼的字符串中查找第 10 個字符,很容易計算出它位于第 37 個字節處,直接獲取就行,不用再逐個遍歷字符了,沒有比這更快的定位字符的方法了。
但是,UTF-32 的缺點也很明顯,就是太占用存儲空間了,在網絡傳輸時也會消耗很多流量。所以UTF-32 在應用上不如 UTF-8 和 UTF-16 廣泛。
3、UTF-16 可以看做是 UTF-8 和 UTF-32 的折中方案,它平衡了存儲空間和處理效率的矛盾。對于常用的字符,40用兩個字節存儲足以,這個時候 UTF-16 是不需要轉換的,直接存儲字符的編碼值即可。
>Windows 內核、.NET Framework、Cocoa、Java String 內部采用的都是 UTF-16 編碼。UTF-16 是幕后的功臣,我們在編輯源代碼和文檔時都是站在前臺,所以一般感受不到,其實很多文本在后臺處理時都已經轉換成了 UTF-16 編碼。不過,UNIX 家族的操作系統(Linux、Mac OS、iOS 等)內核都采用 UTF-8 編碼,
在Windows系統中,ANSI編碼代表本地編碼的意思。換言之,在簡體中文Windows操作系統中,ANSI 編碼代表 GBK 編碼;在日文Windows操作系統中,ANSI 編碼代表 Shift_JIS 編碼。
參見我的另外一篇博客:[【字符集二】多字節字符vs寬字符])
各位朋友,你們好。
今天要和大家分享一套函數(確實不知道該用哪個量詞了,就覺得這個還算貼切點),主要是涉及文本的計數、截取、查找、替換等處理的。相信很多朋友都已經猜到了,那么先讓這些函數來亮個相:
注意:由于內容較多,此文要分為幾個部分講解,今天講解第一部分。今天的內容是基礎,其中有很多干貨,需要閱讀并理解,后面的部分才能明白。
一套16個函數
這么多函數,為什么要在一篇文章中講,而不是單獨一個一個講呢?原因有以下幾點:
1、這些函數多是一類函數,在實際使用中,用這個可以實現效果、用那個也可以達到目的,所以放在一起講,可以把更多的解題思路放在一起做對比;
2、還有一些函數,其功能和作用相同或相近,那么究竟什么情況下用這個,什么情況下又用那個呢?對比來講,可以把函數的相同點和不同點做對比,在選擇函數的時候,就不會出錯了;
3、以上這些函數,經常組隊出現,在解釋一個例子的時候,就可以更詳細的分析函數和函數的結果。
在開始的時候,需要先給大家普及一點基礎內容,就是Office內容的默認編碼語言。我們用【LEN】和【LENB】函數來舉例,先看下官方的解釋:
官方對字符、字節的解釋
我們需要明白:
1、這兩個函數在計算的時候,使用的字符集的語言不一致,所以結果會不一樣;
2、LEN函數不受默認語言設置的影響;
3、LENB函數要受默認語言設置的影響:只有當啟用支持 DBCS 的語言的編輯并將其設置為默認語言時,LENB函數才會將每個雙字節字符按 2 計數,否則結果和LEN函數一樣;
4、支持 DBCS 的語言包括日語、中文(簡體)、中文(繁體)以及朝鮮語。
5、只有當我們的Office語言設置成中文(簡體或繁體)、日語、朝鮮語時,LENB才會將每個雙字節字符按 2 計數;設置為其他語言時,函數 LENB 會將每個字符按 1 計數。(所以,當,LENB函數的結果不正常時,可以檢查下Office默認語言是否設置正確,見下圖)
當默認語言設置為英語時,LENB計算漢字的長度為1,而不是2
那么,我們該如何設置、或者如何查看當前計算機的Office默認語言設置呢?(我以Win7系統為例,因為沒有Win8和Win10系統,無法截圖和說明),看下面的流程指引:
開始菜單 → 所有程序 → Microsoft Office → Microsoft Office 2010 工具 → Microsoft Office 2010 語言首選項
Microsoft Office 2010 語言首選項
工具的設置界面如下:
Microsoft Office 2010 語言首選項設置界面
同理,MIDB、LEFTB、RIGHTB、SEARCHB、FINDB、REPLACEB這幾個函數,情況和這個一樣。
接下來,我們后面所有的案例和操作,均是建立在中文為Office默認語言的基礎上,特此申明。
涉及文本處理,字節和字符這兩個概念是必須要弄清楚的:計算機存儲容量基本單位是字節(Byte),所以在按字節處理文本的函數最后面,都比普通函數多了一個字母【B】,這點就非常好辨識。
【字符、字節】:一般而言,一個標準英文字母占一個字節位置,一個標準漢字占二個字節位置。
【全角、半角】:人們把一個英文字符所占的位置稱為"半角",相對地把一個漢字所占的位置稱為"全角"。所以,全角對漢字無影響,對英文字母、符號、數字來說,在半角狀態它們被作為英文字符處理;而在全角狀態,它們又可作為中文字符處理。
接下來我們用一張圖片,來看下全角、半角的差異:
字母、數字、漢字在全角和半角下,字節數的差異
所以,我們后面所有的案例和操作,均是建立在以半角狀態錄入的數據基礎上,再次申明。
上面看了字母、數字、漢字的字符數與字節數的對比,接下來我們再看看,中文的符號和英文的符號,字節數有什么不同:
中文的符號和英文的符號,字節數的差異
如上圖所示,中文的絕大部分符號,都是占的2個字節、英文符號都是占1個字符。所以在實際應用的時候,一定要先確認內容中所用的符號是英文的還是中文的,因為這可能會對結算結果造成影響,相對難確認的就如小括號、加號、冒號、逗號等,我們看看下圖的效果:
如圖所示,中文的符號所占的位置是2個字節,而英文的符號占的位置是1個字節,轉換為直觀上的差異就是:中文的符號占的位置寬,英文的符號占的位置窄。(加號作為運算符,一般不會直接再單元格中顯示,故不做區別)
不知不覺已經1600多字了。今天的基礎內容就講解到這里,看完后,相信大家一定有所收獲,也知道了一些以前不知道的內容吧?是否還繼續期待后續的更新呢?我們明天繼續更新。歡迎大家持續關注。
如果你喜歡我分享的內容,請點個贊支持下;
如果你覺得我分享的內容對你有幫助,可以關注我;
如果要看我以前分享過的好玩的內容,大家可以去我的主頁查看歷史文章。