成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

通過javascript進(jìn)行UTF-8編碼

jone5679 / 2406人閱讀

摘要:通過進(jìn)行編碼的字符集程序是使用字符集編寫的。這種情況下,我們必須就要通過程序?qū)⒌淖址D(zhuǎn)為編碼的字符串。英文占個(gè)字符,漢字占個(gè)字符然而,的編碼結(jié)構(gòu)長度是根據(jù)某單個(gè)字符的大小來決定長度有多少。把英文字母轉(zhuǎn)為編碼。

通過javascript進(jìn)行UTF-8編碼 javascript的字符集:

javascript程序是使用Unicode字符集編寫的。UnicodeASCIILatin-1的超集,并支持地球上幾乎所有的語言。ECMAScript3要求JavaScript必須支持Unicode2.1及后續(xù)版本,ECMAScript5則要求支持Unicode3及后續(xù)版本。所以,我們編寫出來的javascript程序,都是使用Unicode編碼的。

UTF-8

UTF-8(UTF8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,也是一種前綴碼。

它可以用來表示Unicode標(biāo)準(zhǔn)中的任何字符,且其編碼中的第一個(gè)字節(jié)仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須做少部分修改,即可繼續(xù)使用。因此,它逐漸成為電子郵件、網(wǎng)頁及其他存儲(chǔ)或發(fā)送文字的應(yīng)用中,優(yōu)先采用的編碼。

目前大部分的網(wǎng)站,都是使用的UTF-8編碼。

將javascript生成的Unicode編碼字符串轉(zhuǎn)為UTF-8編碼的字符串

如標(biāo)題所說的應(yīng)用場景十分常見,例如發(fā)送一段二進(jìn)制到服務(wù)器時(shí),服務(wù)器規(guī)定該二進(jìn)制內(nèi)容的編碼必須為UTF-8。這種情況下,我們必須就要通過程序?qū)avascript的Unicode字符串轉(zhuǎn)為UTF-8編碼的字符串。

轉(zhuǎn)換方法

轉(zhuǎn)換之前我們必須了解Unicode的編碼結(jié)構(gòu)是固定的。
不信可以試一試 String 的 charCodeAt 這個(gè)方法,看看返回的 charCode 占幾個(gè)字節(jié)。

英文占1個(gè)字符,漢字占2個(gè)字符

然而,UTF-8的編碼結(jié)構(gòu)長度是根據(jù)某單個(gè)字符的大小來決定長度有多少。
下面為單個(gè)字符的大小占用幾個(gè)字節(jié)。單個(gè)unicode字符編碼之后的最大長度為6個(gè)字節(jié)。

1個(gè)字節(jié):Unicode碼為0 - 127

2個(gè)字節(jié):Unicode碼為128 - 2047

3個(gè)字節(jié):Unicode碼為2048 - 0xFFFF

4個(gè)字節(jié):Unicode碼為65536 - 0x1FFFFF

5個(gè)字節(jié):Unicode碼為0x200000 - 0x3FFFFFF

6個(gè)字節(jié):Unicode碼為0x4000000 - 0x7FFFFFFF

具體請看圖片:

因?yàn)橛⑽暮陀⑽淖址腢nicode碼為0 - 127,所以英文在Unicode和UTF-8中的長度和字節(jié)都是一致的,只占用1個(gè)字節(jié)。這也就是為什么UTF8是Unicode的超集!

現(xiàn)在我們再來討論漢字,因?yàn)闈h字的unicode碼區(qū)間為0x2e80 - 0x9fff, 所以漢字在UTF8中的長度最長為3個(gè)字節(jié)。

那么漢字是如何從Unicode的2個(gè)字節(jié)轉(zhuǎn)換為UTF8的三個(gè)字節(jié)的哪?

假設(shè)我需要把漢字"中"轉(zhuǎn)為UTF-8的編碼

1、獲取漢字Unicode值大小
var str = "中";
var charCode = str.charCodeAt(0);
console.log(charCode); // => 20013
2、根據(jù)大小判斷UTF8的長度

由上一步我們得到漢字"中"的charCode為20013.然后我們發(fā)現(xiàn)20013位于2048 - 0xFFFF這個(gè)區(qū)間里,所以漢字"中"應(yīng)該在UTF8中占3個(gè)字節(jié)。

3、補(bǔ)碼

既然知道漢字"中"需要占3個(gè)字節(jié),那么這3個(gè)字節(jié)如何得到哪?

這就需要設(shè)計(jì)到補(bǔ)碼,具體補(bǔ)碼邏輯如下:

好吧,我知道這個(gè)圖你們也看不明白,還是我來講吧!

具體的補(bǔ)位碼如下,"x"表示空位,用來補(bǔ)位的。

0xxxxxxx

110xxxxx 10xxxxxx

1110xxxx 10xxxxxx 10xxxxxx

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

warning:有沒有發(fā)現(xiàn)?補(bǔ)位碼第一個(gè)字節(jié)前面有幾個(gè)1就表示整個(gè)UTF-8編碼占多少個(gè)字節(jié)!UTF-8解碼為Unicode就是利用的這個(gè)特點(diǎn)哦~

我們先舉個(gè)簡單的例子。把英文字母"A"轉(zhuǎn)為UTF8編碼。
1、“A”的charCode為65
2、65位于0-127的區(qū)間,所以“A”占一個(gè)字節(jié)
3、UTF8中一個(gè)字節(jié)的補(bǔ)位為0xxxxxxx,x表示的是空位,是用來補(bǔ)位的。
4、將65轉(zhuǎn)為二進(jìn)制得到1000001
5、將1000001按照從前到后的順序,依次補(bǔ)到1xxxxxxx的空位中,得到01000001
6、將11000001轉(zhuǎn)為字符串,得到"A"
7、最終,"A"為UTF8編碼之后“A”

通過這個(gè)小例子,我們是否再次驗(yàn)證了UTF-8是Unicode的超集

好了,我們現(xiàn)在再回到漢字"中"上,之前我們已經(jīng)得到了"中"的charCode為20013,二進(jìn)制為01001110 00101101。具體如下:

var code = 20013;
code.toString(2); 
// => 100111000101101 等同于 01001110 00101101

然后,我們按照上面“A”補(bǔ)位的方法,來給"中"補(bǔ)位。
01001110 00101101按照從前到后的順序依此補(bǔ)位到1110xxxx 10xxxxxx 10xxxxxx上.得到11100100 10111000 10101101.

4、得到UTF8編碼的內(nèi)容

通過上面的步驟,我們得到了"中"的三個(gè)UTF8字節(jié),11100100 10111000 10101101。
我們將每個(gè)字節(jié)轉(zhuǎn)為16進(jìn)制,得到0xE4 0xB8 0xAD;
那么這個(gè)0xE4 0xB8 0xAD就是我們最終得到的UTF8編碼了。

我們使用nodejs的buffer來驗(yàn)證一下是否正確。

var buffer = new Buffer("中"); 
console.log(buffer.length); // => 3
console.log(buffer); // => 
// 最終得到三個(gè)字節(jié) 0xe4 0xb8 0xad

因?yàn)?6進(jìn)制是不分大小寫的,所以是不是跟我們算出來0xE4 0xB8 0xAD一模一樣。

將上面的編碼邏輯寫到一個(gè)函數(shù)中。
// 將字符串格式化為UTF8編碼的字節(jié)
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字節(jié)的長度。因?yàn)殚L度為3,所以前兩個(gè)字節(jié)為`0,3`
// 內(nèi)容為`228, 184, 173`轉(zhuǎn)成16進(jìn)制就是`0xE4 0xB8 0xAD`
// 讀取UTF8編碼的字節(jié),并專為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字節(jié)碼的方法

另外一種比較簡單的將中文轉(zhuǎn)為UTF8字節(jié)碼的方法比較簡單,瀏覽器也提供了一個(gè)方法,而且這個(gè)方法大家都一直在用,是什么哪?就是encodeURI。當(dāng)然,encodeURIComponent也是可以的。
沒錯(cuò),就是這個(gè)方法。那么這個(gè)方法是怎么將一個(gè)Unicode編碼的中文轉(zhuǎn)為UTF8的字節(jié)碼嘞?

var str = "中";

var code = encodeURI(str);

console.log(code); // => %E4%B8%AD

有沒有發(fā)現(xiàn)得到了一個(gè)轉(zhuǎn)義后的字符串,而且這個(gè)字符串中的內(nèi)容和我之前在上面得到的字節(jié)碼是一樣的~~~。

下面我們將%E4%B8%AD轉(zhuǎn)為一個(gè)number數(shù)組。

var codeList = code.split("%");

codeList = codeList.map(item => parseInt(item,16));

console.log(codeList); // => [228, 184, 173]

如此簡單,有木有~~~

這個(gè)簡便方法的原理是什么?

這里就涉及到的URI中的querystring編碼的問題了。因?yàn)榘凑找?guī)定,URI中的querystring必須按照UTF8的編碼進(jìn)行傳輸,而JavaScript是Unicode的,所以瀏覽器就給我們提供了一個(gè)方法,也就是encodeURI/encodeURIComponent方法。這個(gè)方法會(huì)講非英文字符(這里考慮下,為什么是非英文字符?)先轉(zhuǎn)為UTF8的字節(jié)碼,然后前面加個(gè)%進(jìn)行拼接,所以我們將漢字"中"轉(zhuǎn)義下便得到了"%E4%B8%AD".
好吧,原理就這些,沒有其他的了。

不過,這種方法還有個(gè)缺點(diǎn),那就是只會(huì)轉(zhuǎn)義非英文字符,所以當(dāng)我們需要將英文字符也格式化為UTF8編碼時(shí),這個(gè)方法是達(dá)不到我們需求的,我們還需要額外的將英文字符也給轉(zhuǎn)義下。

那我想要解析回來應(yīng)該怎么做哪?用decodeURI/decodeURIComponent就可以了。

var codeList = [228, 184, 173];

var code = codeList.map(item => "%"+item.toString(16)).join("");

decodeURI(code); // => 中

好了,到這里本文也就介紹完UTF8的編碼了。
希望可以幫助大家了解到UTF-8編碼的原理。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/79758.html

相關(guān)文章

  • JavaScript如何實(shí)現(xiàn)UTF-16編碼轉(zhuǎn)換為UTF-8編碼——utfx.js源碼解析

    摘要:編碼轉(zhuǎn)換為編碼下面讓我們來看下如何將編碼的數(shù)據(jù)轉(zhuǎn)換為編碼的數(shù)據(jù)。該方法是將碼進(jìn)行編碼轉(zhuǎn)換,從而得到編碼的數(shù)據(jù)。 概述 當(dāng)你在前端需要通過二進(jìn)制數(shù)據(jù)與服務(wù)端進(jìn)行通信時(shí),你可能會(huì)遇到二進(jìn)制數(shù)據(jù)的編碼問題。大部分服務(wù)端的字符串編碼類型都為UTF-8,而JavaScript中字符串編碼類型是UTF-16,因此,你需要一個(gè)能夠?qū)⒆址趦煞N編碼方式間進(jìn)行轉(zhuǎn)換的方法。 本文通過對utfx.js這個(gè)...

    maybe_009 評論0 收藏0
  • Unicode中UTF-8與UTF-16編碼詳解

    摘要:概念是一種針對的可變長度字符編碼,又稱萬國碼。通過上面的介紹我們可以知道,是一種非常通用的可變長字符編碼方式。概念是字符編碼五層次模型的第三層字符編碼表,也稱為的一種實(shí)現(xiàn)方式。 概述 本文通過介紹Unicode編碼以及對應(yīng)的兩種編碼方式UTF-8和UTF-16,讓讀者能夠了解關(guān)于字符串編碼的相關(guān)知識,同時(shí)能夠弄清楚Unicode和UTF-8和UTF-16之間的關(guān)系。 本文的主要內(nèi)容為:...

    cod7ce 評論0 收藏0
  • WebSocket系列之字符串如何與二進(jìn)制數(shù)據(jù)間進(jìn)行互相轉(zhuǎn)換

    摘要:總結(jié)通過使用和,我們能夠在數(shù)據(jù)和二進(jìn)制數(shù)據(jù)中進(jìn)行互相轉(zhuǎn)換。下一篇系列相關(guān)的博客,將會(huì)介紹如何通過來向后端傳遞二進(jìn)制數(shù)據(jù),以及如何處理通過收到的二進(jìn)制數(shù)據(jù)。 概述 上一篇博客我們說到了如何進(jìn)行數(shù)字類型(如Short、Int、Long類型)如何在JavaScript中進(jìn)行二進(jìn)制轉(zhuǎn)換,如果感興趣的可以可以閱讀本系列第二篇博客——WebSocket系列之JavaScript中數(shù)字?jǐn)?shù)據(jù)如何轉(zhuǎn)換為...

    stackfing 評論0 收藏0
  • Linux下文件名長度限制

    摘要:下文件名長度限制出現(xiàn)場景在迭代中有一個(gè)需求是將文件名修改為所有班級的名稱集合,出現(xiàn)的班級過多導(dǎo)致的文件名過長在下無法創(chuàng)建文件和文件夾的情況解決方式經(jīng)過查證,中文件名最長為字符,文件路徑最大長度為字符。這是被編碼方案決定的,通過來指定。 Linux下文件名長度限制 出現(xiàn)場景:在迭代中有一個(gè)需求是將pdf文件名修改為所有班級的名稱集合,出現(xiàn)的班級過多導(dǎo)致的文件名過長在linux下無法創(chuàng)建文...

    entner 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<