成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

maybe_009 / 3580人閱讀

摘要:編碼轉換為編碼下面讓我們來看下如何將編碼的數(shù)據(jù)轉換為編碼的數(shù)據(jù)。該方法是將碼進行編碼轉換,從而得到編碼的數(shù)據(jù)。

概述

當你在前端需要通過二進制數(shù)據(jù)與服務端進行通信時,你可能會遇到二進制數(shù)據(jù)的編碼問題。大部分服務端的字符串編碼類型都為UTF-8,而JavaScript中字符串編碼類型是UTF-16,因此,你需要一個能夠將字符串在兩種編碼方式間進行轉換的方法。

本文通過對utfx.js這個庫的代碼進行分析,帶大家深入了解UTF8和UTF16這兩種編碼方式在JavaScript中的轉換方法,同時加深對Unicode中UTF-8和UTF-16兩種編碼方式的具體原理的理解。

本文的主要內(nèi)容為:

utfx.js API簡單介紹

UTF-16編碼轉換為UTF-8編碼

UTF-8編碼字符串長度計算

實驗性功能:window.TextEncoder

如果有讀者不了解Unicode中UTF-8和UTF-16兩種編碼方式的具體原理,可以閱讀我的前一篇博客——Unicode中UTF-8與UTF-16編碼詳解。

如果有讀者想要了解該庫相關的轉換使用場景,可以閱讀我之前的博客WebSocket系列之JavaScript字符串如何與二進制數(shù)據(jù)間進行互相轉換。

utfx.js API簡介

在進行具體的代碼詳解之前,我們先來了解下我們需要介紹的庫——utfx.js。我們只有了解了這個庫的使用方法,我們才能夠更好的理解源碼。

utfx.js代碼不多,一共只有八個API接口,分別為:

encodeUTF8:將UTF-8編碼的字符串code碼轉換為二進制bytes。

decodeUTF8:將UTF-8編碼的二進制bytes解碼城字符串code碼。

UTF16toUTF8:將UTF-16的字符轉換為UTF-8的code碼。

UTF8toUTF16:將UTF-8的code碼轉換為UTF-16的字符。

encodeUTF16toUTF8:將UTF-16編碼的字符轉換為UTF-8編碼的bytes。

decodeUTF8toUTF16:將UTF-8編碼的bytes轉換為UTF-16編碼的字符。

calculateCodePoint:計算UTF-8編碼下的字符長度。

calculateUTF8:計算需要用來存儲UTF-8編碼code碼的bytes的長度。

calculateUTF16asUTF8:計算UTF-16編碼的字符在轉換成UTF-8后需要的存儲長度。

下面,我們將挑選幾個具有代表性的API,針對其實現(xiàn)的具體代碼來進行分析,幫助大家快速理解這兩種編碼方式。

UTF-16編碼轉換為UTF-8編碼

下面讓我們來看下如何將UTF-16編碼的數(shù)據(jù)轉換為UTF-8編碼的數(shù)據(jù)。

當我們需要把UTF-16的數(shù)據(jù)轉換為UTF-8編碼的數(shù)據(jù)時,最好的方法肯定是將UTF-16編碼的數(shù)據(jù)轉換為通用的Unicode碼,在進行UTF-8編碼。我們通過UTF16toUTF8和encodeUTF8方法的代碼來進行具體解析。

UTF16toUTF8

這個函數(shù)名看上去是直接將UTF-16編碼的bytes數(shù)據(jù)轉換為UTF-8編碼的的Bytes數(shù)據(jù)。其實是,將UTF-16編碼的bytes數(shù)據(jù)轉換為Unicode對應的二進制數(shù)據(jù)

/**
 * UTF16數(shù)據(jù)轉換到Unicode數(shù)據(jù)
 * @param src 數(shù)據(jù)源,類型為Function,調(diào)用一次返回1 Byte數(shù)據(jù),如果到達字符串末尾則返回null
 * @param dst 處理函數(shù),類型為Function,得到的Bytes作為參數(shù)傳遞給dst函數(shù)
 */
utfx.UTF16toUTF8 = function (src, dst) {
    var c1, c2 = null;
    while (true) {
        // 到達結尾調(diào)用src函數(shù)得到null后會進入此分支邏輯
        if ((c1 = c2 !== null ? c2 : src()) === null)
            break;
        
        //Unicode標準規(guī)定,U+D800~U+DFFF的值不對應任何字符,即專門用來判斷是否為高位代理
        if (c1 >= 0xD800 && c1 <= 0xDFFF) {
            if ((c2 = src()) !== null) {
                // 如果Unicode碼范圍超過U+FFFF則會進入此分支邏輯(兩段:第一段大于U+D800,第二段大于U+DC00)
                if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
                    // 第一步:用c1還原高10位;第二步:用c2還原低十位;第三步:加上減去的0x10000
                    dst((c1 - 0xD800) * 0x400 + c2 - 0xDC00 + 0x10000);
                    c2 = null; continue;
                }
            }
        }
        dst(c1);
    }
    if (c2 !== null) dst(c2);
};

根據(jù)代碼和上面的注釋,大家應該就能看懂對應代碼,因此在此不做過多贅述。我們接著看將Unicode碼轉換為UTF-8編碼的方法。

encodeUTF8

該方法是將Unicode碼進行UTF-8編碼轉換,從而得到UTF-8編碼的Bytes數(shù)據(jù)。

/**
 * Unicode數(shù)據(jù)轉換為UTF-8數(shù)據(jù)
 * @param src 數(shù)據(jù)源,類型為Function,調(diào)用一次返回1 Byte數(shù)據(jù),如果到達字符串末尾則返回null
 * @param dst 處理函數(shù),類型為Function,得到的Bytes作為參數(shù)傳遞給dst函數(shù)
 */
utfx.encodeUTF8 = function (src, dst) {
    var cp = null;
    if (typeof src === "number")
        cp = src,
            src = function () {return null;};
    while (cp !== null || (cp = src()) !== null) {
        if (cp < 0x80)
        // 1 byte存儲情況
            dst(cp & 0x7F);
        else if (cp < 0x800)
        // 2 byte存儲情況
            dst(((cp >> 6) & 0x1F) | 0xC0),
            dst((cp & 0x3F) | 0x80);
        else if (cp < 0x10000)
        // 3 byte存儲情況
            dst(((cp >> 12) & 0x0F) | 0xE0),
            dst(((cp >> 6) & 0x3F) | 0x80),
            dst((cp & 0x3F) | 0x80);
        else
        // 4 byte存儲情況
            dst(((cp >> 18) & 0x07) | 0xF0),
            dst(((cp >> 12) & 0x3F) | 0x80),
            dst(((cp >> 6) & 0x3F) | 0x80),
            dst((cp & 0x3F) | 0x80);
        cp = null;
    }
};

上面的代碼與UTF-8編碼規(guī)范中的方式基本一致,如果沒有理解相關規(guī)范,可以先閱讀本文概述中提到的前一篇博客。

編碼字符串長度計算

當我們給出一串Unicode碼時,我們需要知道申請多大的ArrayBuffer來進行轉換后的數(shù)據(jù)存儲。正好,這個庫還提供了根據(jù)Unicode碼的長度或者UTF-16編碼格式的數(shù)據(jù)來計算UTF-8數(shù)據(jù)的存儲長度。

下面我們來介紹calculateUTF8calculateUTF16asUTF8這兩個方法。

calculateUTF8

該方法是通過Unicode碼來計算轉換為UTF-8編碼后所占存儲長度。

/**
 * 根據(jù)Unicode編碼來計算轉換成UTF-8編碼后需要的存儲長度
 * @param src 數(shù)據(jù)源,類型為Function,調(diào)用一次返回1 Byte數(shù)據(jù),如果到達字符串末尾則返回null
 */
utfx.calculateUTF8 = function (src) {
    var cp, l = 0;
    while ((cp = src()) !== null)
        // 占1 Byte的范圍是0~0x7F;占2 Byte的范圍是0x80~0x7FF;占三個字節(jié)的范圍是0x800~0xFFFF;占4個字節(jié)的范圍為:0x10000~0x10FFFF
        l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
    return l;
};

根據(jù)上面的的代碼和UTF-8的編碼規(guī)范,我們就能夠很容易理解這種寬度計算的方法。

calculateUTF16asUTF8

該方法是通過UTF16的數(shù)據(jù)來計算轉換為Unicode碼和轉換為UTF-8編碼后所占存儲長度。

/**
 * 根據(jù)UTF-16編碼的Bytes來計算轉換為Unicode的長度和轉換成UTF-8編碼后需要的存儲長度
 * @param src 數(shù)據(jù)源,類型為Function,調(diào)用一次返回1 Byte數(shù)據(jù),如果到達字符串末尾則返回null
 */
utfx.calculateUTF16asUTF8 = function (src) {
    var n = 0, l = 0;
    utfx.UTF16toUTF8(src, function (cp) {
        ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
    });
    return [n, l];
};

該方法通過之前介紹的將UTF-16編碼轉換為Unicode碼的方法獲取到Unicode數(shù)據(jù),再進行計算,返回了Unicode碼的長度和UTF-8編碼后長度。

window.TextEncoder與Window.TextDecoder

這是兩個處在實驗性的新構造函數(shù),通過創(chuàng)建編碼器(TextEncode對象)和解碼器(TextDecode對象)來實現(xiàn)JavaScript中string類型與UTF-8編碼數(shù)據(jù)中的互相轉換。

構造方法將會返回一個UTF-8編碼的,使用方法如下:

let encoder = new TextEncoder();
let decoder = new TextDecoder();

let unit8Array = encoder.encode("a"); // 返回一個Unit8Array類型——[97]
let str = decoder.decode(arr); // 返回一個值為"a"的字符串

目前,這項新技術的的兼容性仍然存在很大問題,只有Chrome 38、Firefox 19以及Opera 25以上才支持,其他主流的瀏覽器如IE和Safari都還沒有任何支持,因此在生產(chǎn)環(huán)節(jié)中需要慎重使用。

總結

本文對實現(xiàn)了Unicode中UTF-8和UTF-16這兩種編碼方式的庫——utfx.js進行了部分代碼分析。通過看到具體的代碼實現(xiàn),相信大家應該能夠更加好的理解這兩種編碼方式的具體規(guī)范,以及對應的使用方式和場景。

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

轉載請注明本文地址:http://systransis.cn/yun/94276.html

相關文章

  • Unicode中UTF-8與UTF-16編碼詳解

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

    cod7ce 評論0 收藏0
  • 字符編碼的那些事

    摘要:字符編碼的那些事前言之前看到中對擴展了不少新特性,字符串操作更加友好,比如,,。其中涉及到不少字符編碼的知識,為了更好理解這些新特性,本文對字符編碼相關知識做一個較全面的梳理和總結。 字符編碼的那些事 前言 之前看到ES6中對String擴展了不少新特性,字符串操作更加友好,比如u{1f914},codePointAt(),String.fromCodePoint()。其中涉及到不少字...

    shadajin 評論0 收藏0
  • 字符編碼的那些事

    摘要:字符編碼的那些事前言之前看到中對擴展了不少新特性,字符串操作更加友好,比如,,。其中涉及到不少字符編碼的知識,為了更好理解這些新特性,本文對字符編碼相關知識做一個較全面的梳理和總結。 字符編碼的那些事 前言 之前看到ES6中對String擴展了不少新特性,字符串操作更加友好,比如u{1f914},codePointAt(),String.fromCodePoint()。其中涉及到不少字...

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

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

    stackfing 評論0 收藏0
  • 深入分析 Java Web 中的中文編碼問題

    摘要:文章首發(fā)地址深入分析中的中文編碼問題背景編碼問題一直困擾著程序開發(fā)人員,尤其是在中更加明顯,因為是跨平臺的語言,在不同平臺的編碼之間的切換較多。 文章首發(fā)地址:深入分析 Java Web 中的中文編碼問題 背景: 編碼問題一直困擾著程序開發(fā)人員,尤其是在 Java 中更加明顯,因為 Java 是跨平臺的語言,在不同平臺的編碼之間的切換較多。接下來將介紹 Java 編碼問題出現(xiàn)的根本原...

    jsyzchen 評論0 收藏0

發(fā)表評論

0條評論

maybe_009

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<