摘要:通過進行編碼的字符集程序是使用字符集編寫的。這種情況下,我們必須就要通過程序將的字符串轉為編碼的字符串。英文占個字符,漢字占個字符然而,的編碼結構長度是根據某單個字符的大小來決定長度有多少。把英文字母轉為編碼。
通過javascript進行UTF-8編碼 javascript的字符集:
javascript程序是使用Unicode字符集編寫的。Unicode是ASCII和Latin-1的超集,并支持地球上幾乎所有的語言。ECMAScript3要求JavaScript必須支持Unicode2.1及后續版本,ECMAScript5則要求支持Unicode3及后續版本。所以,我們編寫出來的javascript程序,都是使用Unicode編碼的。
UTF-8UTF-8(UTF8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,也是一種前綴碼。
它可以用來表示Unicode標準中的任何字符,且其編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須做少部分修改,即可繼續使用。因此,它逐漸成為電子郵件、網頁及其他存儲或發送文字的應用中,優先采用的編碼。
目前大部分的網站,都是使用的UTF-8編碼。
將javascript生成的Unicode編碼字符串轉為UTF-8編碼的字符串如標題所說的應用場景十分常見,例如發送一段二進制到服務器時,服務器規定該二進制內容的編碼必須為UTF-8。這種情況下,我們必須就要通過程序將javascript的Unicode字符串轉為UTF-8編碼的字符串。
轉換方法轉換之前我們必須了解Unicode的編碼結構是固定的。
不信可以試一試 String 的 charCodeAt 這個方法,看看返回的 charCode 占幾個字節。
英文占1個字符,漢字占2個字符
然而,UTF-8的編碼結構長度是根據某單個字符的大小來決定長度有多少。
下面為單個字符的大小占用幾個字節。單個unicode字符編碼之后的最大長度為6個字節。
1個字節:Unicode碼為0 - 127
2個字節:Unicode碼為128 - 2047
3個字節:Unicode碼為2048 - 0xFFFF
4個字節:Unicode碼為65536 - 0x1FFFFF
5個字節:Unicode碼為0x200000 - 0x3FFFFFF
6個字節:Unicode碼為0x4000000 - 0x7FFFFFFF
具體請看圖片:
因為英文和英文字符的Unicode碼為0 - 127,所以英文在Unicode和UTF-8中的長度和字節都是一致的,只占用1個字節。這也就是為什么UTF8是Unicode的超集!
現在我們再來討論漢字,因為漢字的unicode碼區間為0x2e80 - 0x9fff, 所以漢字在UTF8中的長度最長為3個字節。
那么漢字是如何從Unicode的2個字節轉換為UTF8的三個字節的哪?
假設我需要把漢字"中"轉為UTF-8的編碼
1、獲取漢字Unicode值大小var str = "中"; var charCode = str.charCodeAt(0); console.log(charCode); // => 200132、根據大小判斷UTF8的長度
由上一步我們得到漢字"中"的charCode為20013.然后我們發現20013位于2048 - 0xFFFF這個區間里,所以漢字"中"應該在UTF8中占3個字節。
3、補碼既然知道漢字"中"需要占3個字節,那么這3個字節如何得到哪?
這就需要設計到補碼,具體補碼邏輯如下:
好吧,我知道這個圖你們也看不明白,還是我來講吧!
具體的補位碼如下,"x"表示空位,用來補位的。
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
warning:有沒有發現?補位碼第一個字節前面有幾個1就表示整個UTF-8編碼占多少個字節!UTF-8解碼為Unicode就是利用的這個特點哦~
我們先舉個簡單的例子。把英文字母"A"轉為UTF8編碼。
1、“A”的charCode為65
2、65位于0-127的區間,所以“A”占一個字節
3、UTF8中一個字節的補位為0xxxxxxx,x表示的是空位,是用來補位的。
4、將65轉為二進制得到1000001
5、將1000001按照從前到后的順序,依次補到1xxxxxxx的空位中,得到01000001
6、將11000001轉為字符串,得到"A"
7、最終,"A"為UTF8編碼之后“A”
通過這個小例子,我們是否再次驗證了UTF-8是Unicode的超集!
好了,我們現在再回到漢字"中"上,之前我們已經得到了"中"的charCode為20013,二進制為01001110 00101101。具體如下:
var code = 20013; code.toString(2); // => 100111000101101 等同于 01001110 00101101
然后,我們按照上面“A”補位的方法,來給"中"補位。
將01001110 00101101按照從前到后的順序依此補位到1110xxxx 10xxxxxx 10xxxxxx上.得到11100100 10111000 10101101.
通過上面的步驟,我們得到了"中"的三個UTF8字節,11100100 10111000 10101101。
我們將每個字節轉為16進制,得到0xE4 0xB8 0xAD;
那么這個0xE4 0xB8 0xAD就是我們最終得到的UTF8編碼了。
我們使用nodejs的buffer來驗證一下是否正確。
var buffer = new Buffer("中"); console.log(buffer.length); // => 3 console.log(buffer); // =>// 最終得到三個字節 0xe4 0xb8 0xad
因為16進制是不分大小寫的,所以是不是跟我們算出來0xE4 0xB8 0xAD一模一樣。
將上面的編碼邏輯寫到一個函數中。// 將字符串格式化為UTF8編碼的字節 var writeUTF = function (str, isGetBytes) { var back = []; var byteSize = 0; for (var i = 0; i < str.length; i++) { var code = str.charCodeAt(i); if (0x00 <= code && code <= 0x7f) { byteSize += 1; back.push(code); } else if (0x80 <= code && code <= 0x7ff) { byteSize += 2; back.push((192 | (31 & (code >> 6)))); back.push((128 | (63 & code))) } else if ((0x800 <= code && code <= 0xd7ff) || (0xe000 <= code && code <= 0xffff)) { byteSize += 3; back.push((224 | (15 & (code >> 12)))); back.push((128 | (63 & (code >> 6)))); back.push((128 | (63 & code))) } } for (i = 0; i < back.length; i++) { back[i] &= 0xff; } if (isGetBytes) { return back } if (byteSize <= 0xff) { return [0, byteSize].concat(back); } else { return [byteSize >> 8, byteSize & 0xff].concat(back); } } writeUTF("中"); // => [0, 3, 228, 184, 173] // 前兩位表示后面utf8字節的長度。因為長度為3,所以前兩個字節為`0,3` // 內容為`228, 184, 173`轉成16進制就是`0xE4 0xB8 0xAD`
// 讀取UTF8編碼的字節,并專為Unicode的字符串 var readUTF = function (arr) { if (typeof arr === "string") { return arr; } var UTF = "", _arr = this.init(arr); for (var i = 0; i < _arr.length; i++) { var one = _arr[i].toString(2), v = one.match(/^1+?(?=0)/); if (v && one.length == 8) { var bytesLength = v[0].length; var store = _arr[i].toString(2).slice(7 - bytesLength); for (var st = 1; st < bytesLength; st++) { store += _arr[st + i].toString(2).slice(2) } UTF += String.fromCharCode(parseInt(store, 2)); i += bytesLength - 1 } else { UTF += String.fromCharCode(_arr[i]) } } return UTF } readUTF([0, 3, 228, 184, 173]); => "中"另外一種將中文解析得到UTF8字節碼的方法
另外一種比較簡單的將中文轉為UTF8字節碼的方法比較簡單,瀏覽器也提供了一個方法,而且這個方法大家都一直在用,是什么哪?就是encodeURI。當然,encodeURIComponent也是可以的。
沒錯,就是這個方法。那么這個方法是怎么將一個Unicode編碼的中文轉為UTF8的字節碼嘞?
var str = "中"; var code = encodeURI(str); console.log(code); // => %E4%B8%AD
有沒有發現得到了一個轉義后的字符串,而且這個字符串中的內容和我之前在上面得到的字節碼是一樣的~~~。
下面我們將%E4%B8%AD轉為一個number數組。
var codeList = code.split("%"); codeList = codeList.map(item => parseInt(item,16)); console.log(codeList); // => [228, 184, 173]
如此簡單,有木有~~~
這個簡便方法的原理是什么?這里就涉及到的URI中的querystring編碼的問題了。因為按照規定,URI中的querystring必須按照UTF8的編碼進行傳輸,而JavaScript是Unicode的,所以瀏覽器就給我們提供了一個方法,也就是encodeURI/encodeURIComponent方法。這個方法會講非英文字符(這里考慮下,為什么是非英文字符?)先轉為UTF8的字節碼,然后前面加個%進行拼接,所以我們將漢字"中"轉義下便得到了"%E4%B8%AD".
好吧,原理就這些,沒有其他的了。
不過,這種方法還有個缺點,那就是只會轉義非英文字符,所以當我們需要將英文字符也格式化為UTF8編碼時,這個方法是達不到我們需求的,我們還需要額外的將英文字符也給轉義下。
那我想要解析回來應該怎么做哪?用decodeURI/decodeURIComponent就可以了。
var codeList = [228, 184, 173]; var code = codeList.map(item => "%"+item.toString(16)).join(""); decodeURI(code); // => 中
好了,到這里本文也就介紹完UTF8的編碼了。
希望可以幫助大家了解到UTF-8編碼的原理。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79758.html
摘要:編碼轉換為編碼下面讓我們來看下如何將編碼的數據轉換為編碼的數據。該方法是將碼進行編碼轉換,從而得到編碼的數據。 概述 當你在前端需要通過二進制數據與服務端進行通信時,你可能會遇到二進制數據的編碼問題。大部分服務端的字符串編碼類型都為UTF-8,而JavaScript中字符串編碼類型是UTF-16,因此,你需要一個能夠將字符串在兩種編碼方式間進行轉換的方法。 本文通過對utfx.js這個...
摘要:概念是一種針對的可變長度字符編碼,又稱萬國碼。通過上面的介紹我們可以知道,是一種非常通用的可變長字符編碼方式。概念是字符編碼五層次模型的第三層字符編碼表,也稱為的一種實現方式。 概述 本文通過介紹Unicode編碼以及對應的兩種編碼方式UTF-8和UTF-16,讓讀者能夠了解關于字符串編碼的相關知識,同時能夠弄清楚Unicode和UTF-8和UTF-16之間的關系。 本文的主要內容為:...
摘要:總結通過使用和,我們能夠在數據和二進制數據中進行互相轉換。下一篇系列相關的博客,將會介紹如何通過來向后端傳遞二進制數據,以及如何處理通過收到的二進制數據。 概述 上一篇博客我們說到了如何進行數字類型(如Short、Int、Long類型)如何在JavaScript中進行二進制轉換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數字數據如何轉換為...
摘要:下文件名長度限制出現場景在迭代中有一個需求是將文件名修改為所有班級的名稱集合,出現的班級過多導致的文件名過長在下無法創建文件和文件夾的情況解決方式經過查證,中文件名最長為字符,文件路徑最大長度為字符。這是被編碼方案決定的,通過來指定。 Linux下文件名長度限制 出現場景:在迭代中有一個需求是將pdf文件名修改為所有班級的名稱集合,出現的班級過多導致的文件名過長在linux下無法創建文...
閱讀 1911·2021-11-22 14:44
閱讀 1676·2021-11-02 14:46
閱讀 3664·2021-10-13 09:40
閱讀 2604·2021-09-07 09:58
閱讀 1611·2021-09-03 10:28
閱讀 1663·2019-08-29 15:30
閱讀 982·2019-08-29 15:28
閱讀 1474·2019-08-26 12:20