日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

此文由前美團前端工程師@小魚兒授權發(fā)布

背景

在日常開發(fā)中很少接觸到字符的概念,大部分語言對字符的轉換都已經封裝的足夠好,不需要開發(fā)人員過多考慮編碼解碼的問題。但是字符編碼又經常在開發(fā)中遇見,所以這一篇文章就是解決,到底什么是字符集以及其編碼。舉個很簡單的例子,調用字符串的length函數,其中的英文,漢字,emoji,長度分別是多少?length長度是如何計算的?IOS中的NSString,JAVAscript中的String在內存中的編碼方式是什么?搞懂了字符編碼,這些問題就迎刃而解了。

編碼、ASCII

我們知道計算機只處理0和1,所有可見的文件,視頻,音頻等都是以二進制的形式存儲和運算的。我們用八個二進制位表示一個字節(jié),那么一個字節(jié)就可以代表256種“字符”。舉個例子,字母“A”定義為65,用二進制表示是0100 0001。

徹底搞懂字符編碼

 

這種把A轉換成0100 0001的形式就是一次映射的過程。再來看ASCII碼一共有128個字符,那么就有128個映射。一個字節(jié)就足足的可以表示了。ASCII就是最早期的字符集。

徹底搞懂字符編碼

 

字符集

隨著計算機的普及,需要做映射的字符越來越多,光常用漢字就幾千個了,這時候ASCII碼已經不夠用了,涌現(xiàn)了很多字符集,ISO-8859,GB2312,GBK等,直到后來為了解決各個字符集各自為戰(zhàn)的問題,分別產生了Unicode 組織和 ISO-10646工作小組,最后這兩家組織也合并了,形成現(xiàn)如今的Unicode.

徹底搞懂字符編碼

 

Unicode

Unicode是一種計算行業(yè)標準,用于對世界上大多數書寫系統(tǒng)中表示的文本進行一致的編碼,表示和處理。該標準由Unicode聯(lián)盟維護,截至2019年5月,最新版本Unicode 12.1包含137994個字符的庫,涵蓋150個現(xiàn)代和歷史腳本以及多個符號集和表情符號。Unicode標準的字符庫與ISO / IEC 10646同步,并且兩者的代碼相同。Unicode也是一種字符集。通常會用U+十六進制表示,可存儲0000 ~ 10FFFF 共 1114112 個值,2^16(65536)個號碼組成一個平面,一共有17個平面,其中第一個0號平面占了絕大部分常用的字符??聪聢D可以比較直觀的了解,其中每個最小的格子是一個字節(jié)即代表256個編碼點,每個大格子有65536個編碼點,藍色區(qū)域是已被使用的區(qū)域,綠色是自用區(qū),紅色區(qū)域是代理區(qū)。

徹底搞懂字符編碼

 

再將前三個格子放大,藍綠色部分是漢字,棕色部分是朝鮮語,由這兩張圖可以最直觀的了解Unicode存儲空間。Unicode的實現(xiàn)方式有多種,其中最常用的是UTF-8和UTF-16,下面逐一介紹兩個實現(xiàn)原理。

徹底搞懂字符編碼

 

UTF-8

UTF-8是目前使用最廣的Unicode編碼方式,它是一種可變長的編碼方式,從1個字節(jié)到4個字節(jié)不等。下圖是它的編碼規(guī)則:

1.對于單字節(jié)的符號,字節(jié)的第一位設為0,后面7位為這個符號的 Unicode 碼。因此對于英語字母,UTF-8 編碼和 ASCII 碼是相同的。

2.對于n字節(jié)的符號(n > 1),第一個字節(jié)的前n位都設為1,第n + 1位設為0,后面字節(jié)的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的 Unicode 碼。

徹底搞懂字符編碼

 

根據上表,解讀 UTF-8 編碼非常簡單。如果一個字節(jié)的第一位是0,則這個字節(jié)單獨就是一個字符;如果第一位是1,則連續(xù)有多少個1,就表示當前字符占用多少個字節(jié)。

下面,還是以漢字“嚴”為例,演示如何實現(xiàn) UTF-8 編碼。

“嚴”的 Unicode 是4E25(100111000100101),根據上表,可以發(fā)現(xiàn)4E25處在第三行的范圍內(0000 0800 - 0000 FFFF),因此“嚴”的 UTF-8 編碼需要三個字節(jié),即格式是1110xxxx 10xxxxxx 10xxxxxx。然后,從“嚴”的最后一個二進制位開始,依次從后向前填入格式中的x,多出的位補0。這樣就得到了,“嚴”的 UTF-8 編碼是11100100 10111000 10100101,轉換成十六進制就是E4B8A5。

 

優(yōu)點:

1.兼容ASCII.

2.沒有字節(jié)序問題。(后面會講到字節(jié)序)

3.對于英文編碼較短,占用空間小。

4.可變長,空間足夠大

5.容錯性好,中間丟失字節(jié),后面的字節(jié)還是可以根據編碼規(guī)則解碼,不影響后面的字符生成。

 

缺點:

1.對于中日韓的語言,一個字符需要三個字節(jié)表示,占用空間大。

2.計算長度效率低,由于是變長的,所以在計算字符串長度的時候執(zhí)行效率比較低。

 

UTF-16

UTF-16也是經常用到的編碼方式,同樣它也是可變長的編碼方式,下圖是編碼規(guī)則,字符長度2個字節(jié)或者4個字節(jié)表示一個字符。

徹底搞懂字符編碼

 

隨即就有了一個問題,當我們遇到兩個字節(jié),怎么看出它本身是一個字符,還是需要跟其他兩個字節(jié)放在一起解讀形成一個字符?

U+D800到U+DFFF是一個空段,這些碼點不對應任何字符,編號大于U+0FFFF的字符,一半在U+D800到U+DBFF之間,一半在U+DC00到U+DFFF之間,當我們遇到兩個字節(jié),發(fā)現(xiàn)它的碼點在U+D800到U+DBFF之間,就可以斷定,緊跟在后面的兩個字節(jié)的碼點,應該在U+DC00到U+DFFF之間,這四個字節(jié)必須放在一起形成一個字節(jié)。剛好可以涵蓋輔助面的字符。

 

優(yōu)點:

1.由于是固定2個字節(jié)和4個字節(jié),所以在計算字符串長度、執(zhí)行索引操作時速度很快。

缺點:

1.UTF-16 能表示的字符數有 6 萬多,但是實際上目前 Unicode 5.0 收錄的字符已經達到 99024 個字符,早已超過 UTF-16 的存儲范圍。

2.UTF-16 存在字節(jié)序問題(大端和小端)使用時需要提前協(xié)定好。

3.容錯性差,因為存在字節(jié)序的問題,如果中間某一個字節(jié)丟失時可能會導致后面的解碼錯誤。

UTF-32

4 個字節(jié)表示一個代碼值,固定長度,多出來的部分前面補0,這種編碼方式占空間較多,使用場景很少。

字節(jié)序

字節(jié)序是指數據在存儲器中的存放順序,分為大端和小端兩種。之所以會存在字節(jié)序的問題是因為寄存器的長度要大于一個字節(jié),不同的操作系統(tǒng)讀取字節(jié)的順序不一樣,

大端模式,是指數據的高字節(jié)在前,保存在內存的低地址中,與人類的讀寫法一致,數據的低字節(jié)在后,保存在內存的高地址中,文件前綴FE FF。(mac OS是大端模式)

小端模式,是指數據的高字節(jié)在后,保存在內存的高地址中,而數據的低字節(jié)在前,保存在內存的低地址中,文件前綴FF FE。(x86和一般的OS(如windows,F(xiàn)reeBSD,linux)使用的是小端模式)。

徹底搞懂字符編碼

 

所以UTF-16存在一個字節(jié)序的問題,需要在文件前面聲明,而UTF-8不存在這個問題,原因在于UTF-8的最小編碼單位是1個字節(jié),不會存在兩個字節(jié)誰在高位誰在地位的問題。

還是以漢字“嚴”為例,Unicode 碼是4E25,需要用兩個字節(jié)存儲,一個字節(jié)是4E,另一個字節(jié)是25。存儲的時候,4E在前,25在后,這就是 Big endian 方式(4E 25)。25在前,4E在后,這是 Little endian 方式(25 4E)。

 

用途

UTF-8,廣泛用于數據存儲及傳輸:例如html文檔中的<meta charset="UTF-8">,以及Python文件當出現(xiàn)中文的時候會在頂部加上“# coding: UTF-8”等。

UTF-16,而一些流行語言比如Java、JavaScript、Python、Objective-C等字符串內部字符串都用UTF-16編碼.在計算字符串長度搜索是的效率較好。

 

Objective-C中的NSString

徹底搞懂字符編碼

 

Java中的String類

徹底搞懂字符編碼

 

實踐

1.日常字母,漢字,表情分別用UTF-8UTF-16表示分別用多少字節(jié)?

字母UTF-8用一個字節(jié),UTF-16用兩個字節(jié)。

大部分的漢字UTF-8編碼后由三個字節(jié)如下圖的“嚴”是e4b8a5,而用UTF-16編碼僅用2個字節(jié)即4e25。

大部分表情等特殊符號UTF-8編碼后占4個字節(jié),UTF-16編碼后也占4個字節(jié)。

徹底搞懂字符編碼

 

2.字符計算長度length方法是怎么計算的?

像NSString,java,javascript等語言,由于是UTF-16編碼的,在計算長度的時候由總字節(jié)/2得來的。

3.實際開發(fā)時,如果想計算字符實際長度該怎么計算?

1)一種是通過判斷碼點所在位置進行判斷,只要落在0xD800到0xDBFF的區(qū)間,就要連同后面2個字節(jié)一起讀取.

var index = -1;
var string = '12';
var length = string.length;
var output = [];
while (++index < length) {
  var charCode = string.charCodeAt(index);
  var character = string.charAt(index);
  if (charCode >= 55296 && charCode <= 56319) {
    output.push(character + string.charAt(++index));
  } else {
    output.push(character);
  }
}
console.log(output) //["", "1", "2"]
consolo.log(0xD800 ===55296) // true

2.)ECMAScript 6版本 增強了對Unicode的支持,基本解決了這個問題。

let s = '12';
let output = [];
for(let s of string ){ 
    output.push(s)
}
console.log(output) //["", "1", "2"]

Array.from(string).length

4.javascript字符串和碼點之間的轉換方法?

  • String.fromCodePoint():從Unicode碼點返回對應字符
console.log(String.fromCodePoint(9731, 9733, 9842, 0x2F804));
// expected output: "?★?你"

  • String.prototype.codePointAt():從字符返回對應的碼點
var icons = '?★?';
console.log(icons.codePointAt(1));
// expected output: "9733"

5.文件編碼是UTF-8,和字符串UTF-16編碼之間有什么關系?

這里以python為例,我們都知道,磁盤上的文件都是以二進制格式存放的,其中文本文件都是以某種特定編碼的字節(jié)形式存放的。對于程序源代碼文件的字符編碼是由編輯器指定的,比如我們使用Pycharm來編寫Python程序時會指定工程編碼和文件編碼為UTF-8,那么Python代碼被保存到磁盤時就會被轉換為UTF-8編碼對應的字節(jié)(encode過程)后寫入磁盤。當執(zhí)行Python代碼文件中的代碼時,Python解釋器在讀取Python代碼文件中的字節(jié)串之后,需要將其轉換為Unicode字符串(decode過程)之后才執(zhí)行后續(xù)操作。

徹底搞懂字符編碼

 

總結

上面講了Unicode字符集的起源,它的三種編碼方式,UTF-8,UTF-16,UTF-32,編碼空間,編碼規(guī)則,優(yōu)缺點以及用途,之后結合實際場景應用介紹了js中一些實踐方法,不同語言會有自己的方式,還有就是文件編碼和執(zhí)行時字符編碼。這些知識點在實際開發(fā)中不常見,但是深入了解其原理,對日常開發(fā)和解決問題會有幫助。

 

http://reedbeta.com/blog/programmers-intro-to-unicode/

https://zh.wikipedia.org/zh-cn/Unicode#%E6%A8%99%E6%BA%96

http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

http://www.ruanyifeng.com/blog/2014/12/unicode.html

https://www.cnblogs.com/yyds/p/6171340.html

分享到:
標簽:字符 編碼
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰(zhàn)2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定