亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

maybe_009 / 3652人閱讀

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

概述

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

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

本文的主要內容為:

utfx.js API簡單介紹

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

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

實驗性功能:window.TextEncoder

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

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

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,針對其實現的具體代碼來進行分析,幫助大家快速理解這兩種編碼方式。

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

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

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

UTF16toUTF8

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

/**
 * UTF16數據轉換到Unicode數據
 * @param src 數據源,類型為Function,調用一次返回1 Byte數據,如果到達字符串末尾則返回null
 * @param dst 處理函數,類型為Function,得到的Bytes作為參數傳遞給dst函數
 */
utfx.UTF16toUTF8 = function (src, dst) {
    var c1, c2 = null;
    while (true) {
        // 到達結尾調用src函數得到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);
};

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

encodeUTF8

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

/**
 * Unicode數據轉換為UTF-8數據
 * @param src 數據源,類型為Function,調用一次返回1 Byte數據,如果到達字符串末尾則返回null
 * @param dst 處理函數,類型為Function,得到的Bytes作為參數傳遞給dst函數
 */
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來進行轉換后的數據存儲。正好,這個庫還提供了根據Unicode碼的長度或者UTF-16編碼格式的數據來計算UTF-8數據的存儲長度。

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

calculateUTF8

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

/**
 * 根據Unicode編碼來計算轉換成UTF-8編碼后需要的存儲長度
 * @param src 數據源,類型為Function,調用一次返回1 Byte數據,如果到達字符串末尾則返回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;
};

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

calculateUTF16asUTF8

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

/**
 * 根據UTF-16編碼的Bytes來計算轉換為Unicode的長度和轉換成UTF-8編碼后需要的存儲長度
 * @param src 數據源,類型為Function,調用一次返回1 Byte數據,如果到達字符串末尾則返回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數據,再進行計算,返回了Unicode碼的長度和UTF-8編碼后長度。

window.TextEncoder與Window.TextDecoder

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

構造方法將會返回一個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都還沒有任何支持,因此在生產環(huán)節(jié)中需要慎重使用。

總結

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

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

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

相關文章

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

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

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

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

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

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

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

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

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

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

    jsyzchen 評論0 收藏0

發(fā)表評論

0條評論

maybe_009

|高級講師

TA的文章

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