WebSocket系列之字符串怎样与二进制数据间举行相互转换

概述

上一篇博客我们说到了怎样举行数字范例(如Short、Int、Long范例)如安在JavaScript中举行二进制转换,假如感兴致的可以可以浏览本系列第二篇博客——WebSocket系列之JavaScript中数字数据怎样转换为二进制数据。此次,我们来说下string范例的数据怎样举行处置惩罚。
本文是WebSocket系列的第三篇,重要引见string数据与二进制数据之间的转换要领,细致的内容以下:

  • JavaScript中string范例基本知识
  • JavaScript怎样将string范例转换为二进制数据
  • JavaScript怎样将二进制数据转换为string范例
    本文与WebSocket并没有太强关联,不过作为在WebSocket中通报二进制数据的基本知识贮备,因而放入了此系列当中。
    假如读者对WebSocket并不相识,或许说不明白它的运用场景和细节,可以浏览我的本系列的第一篇博客——WebSocket系列之基本知识入门篇

string范例基本知识

string这个范例,关于熟习JavaScript的同砚应当都不生疏,它是属于JavaScript中基本数据范例的一种。不过,我们本日要先引见下DOMString

DOMString 是一个UTF-16字符串。由于JavaScript已运用了如许的字符串,所以DOMString 直接映照到 一个String。将null通报给接收DOMString的要领或参数时一般会把其转换成为“null”。

在WebSocket中举行string范例数据传输时,运用的实在也是DOMString。不过,依据MDN中对DOMString的引见我们可以相识到,大部分一样平常运用场景中,我们可以以为DOMString就是一个string范例。所以,我们只须要相识此范例,运用时依然当做string范例处置惩罚即可。

编码

既然上面提到了UTF-16,那末我们就来简朴引见下UTF-16,以及后端经常使用的UTF-8这两种编码体式格局。
为何须要引见编码范例呢?由于我们在与后端举行字符串数据通报时,可以运用的编码体式格局差别,如许就会致使两边获得差别的数据。因而,我们在举行string的二进制数据通信时,不单单议须要将字符串转换成二进制,还须要协商一致的string编码。

UTF-16

UTF-16 (16-bit Unicode Transformation Format) 是Unicode字符编码五条理模子的第三层:字符编码表(Character Encoding Form,也称为”storage format”)的一种完成体式格局。即把Unicode字符集的笼统码位映照为16位长的整数(即码元)的序列,用于数据存储或通报。

Unicode字符的码位,须要1个或许2个16位长的码元来示意,因而这是一个变长示意。

UTF-16是JavaScript中的string编码范例。

UTF-8

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来示意Unicode范例中的任何字元,且其编码中的第一个字节仍与ASCII兼容,这使得本来处置惩罚ASCII字元的软件不必或只须做少部分修正,即可继承运用。UTF-8运用一至四个字节为每一个字符编码(2003年11月从新范例)。

UTF-8是许多言语运用的通用编码范例,在后端运用中非经常见。

JavaScript中UTF16和UTF-8怎样举行编码转换

在Github上有转换库GitHub – dcodeIO/utfx: A compact library to encode, decode and convert UTF8 / UTF16 in JavaScript.,经由历程这个库,可以将字符串在UTF-8编码和UTF-16编码中举行转换。该库的细致道理和内容以及两种编码体式格局的细致内容申明将会在以后的博客中举行解说。我们下面简朴的引见下它是运用体式格局:

import utfx from './util/utfx';

let str = 'abcdefg';
let result = [];

function stringSource(s) {
    let i = 0;
    return function () {
        return i < s.length ? s.charCodeAt(i++) : null;
    };
}

utfx.encodeUTF16toUTF8(stringSource(str), function (b) {
    result.push(b);
}.bind(this));

同理,该类库供应了其他的要领:

  • decodeUTF8toUTF16,将UTF-8的string数据转换为UTF-16的string数据。
  • calculateUTF16asUTF8,盘算UTF-16编码的string范例范例转换为UTF-8后所占Byte长度。
    这两个要领我们在以后的章节中也会用到。

JavaScript怎样将string范例转换为二进制数据

相识了JavaScript中string范例的编码和在UTF-8和UTF-16之间转换编码的体式格局,下面我们来看下怎样将string范例转换为二进制数据。
起首,我们假定与后端交互时运用的编码体式格局为UTF-8,如许可以满足更多的运用场景。假如依然运用UTF-16的话,则直接疏忽转换编码的逻辑即可。
简朴引见下完成思绪:我们获得一个须要转换的字符串后,先晓得其长度后,初始化ArrayBuffer中相干参数,将数据放入ArrayBuffer中即可。我们将上面的示例稍作修改:

import utfx from './util/utfx';

function stringSource(s) {
    var i = 0;
    return function () {
        return i < s.length ? s.charCodeAt(i++) : null;
    };
}

let str = 'abcdefg';

let strCodes = stringSource(str);
let length = utfx.calculateUTF16asUTF8(strCodes)[1];
let buffer = new ArrayBuffer(length + 4); // 初始化长度为UTF8编码后字符串长度+4个Byte的二进制缓冲区
let view = new DataView(buffer);
let offset = 4;

view.setUint32(0, length); // 将长度安排在字符串的头部

utfx.encodeUTF16toUTF8(stringSource(str), function (b) {
    view.setUint8(offset++, b);
}.bind(this));

经由历程上面的示例,我们就已将一个二进制数据依据UTF-8编码后放入了ArrayBuffer中,同时,将其长度作为一个Unsigned Int范例存储在了二进制头部4个Byte的位置。

JavaScript怎样将二进制数据转换为string范例

晓得了怎样将string范例转换为二进制数据,下面我们看下怎样将全部数据从二进制中读取,转换回string范例。
依据上面转换为二进制的历程,我们不难想到相干的二进制转string范例要领。细致示例以下:

import utfx from './util/utfx';
let str = 'abcdefg';

function stringSource(s) {
    var i = 0;
    return function () {
        return i < s.length ? s.charCodeAt(i++) : null;
    };
}

let strCodes = stringSource(str);
let length = utfx.calculateUTF16asUTF8(strCodes)[1];
let buffer = new ArrayBuffer(length + 4); // 初始化长度为UTF8编码后字符串长度+4个Byte的二进制缓冲区
let view = new DataView(buffer);
let offset = 4;

// 字符串转换二进制历程
view.setUint32(0, length); // 将长度安排在字符串的

utfx.encodeUTF16toUTF8(stringSource(str), function (b) {
    view.setUint8(offset++, b);
}.bind(this));

// 二进制转换字符串历程
let Strlength = view.getUint32(0);
offset = 4;
let result = []; // Unicode编码字符
let end = offset + Strlength;


utfx.decodeUTF8toUTF16(function () {
    return offset < end ? view.getUint8(offset++) : null; // 返回null时会退出此转换函数
}.bind(this), (char) => {
    console.log(char)
    result.push(char);
});

let strResult = result.reduce((prev, next)=>{
    return prev + String.fromCharCode(next);
}, '');

经由历程上面的示例我们可以晓得,我们只须要在前面4个Byte中将字符串长度读取出来,然后再从第4个Byte(从0最先算)的位置最先读取指定长度的字符串字符编码即可。末了,我们获得了一个Unicode码数组,只须要fromCharCode要领即可将其转换为字符串。

总结

经由历程运用ArrayBuffer和DataView,我们可以在string数据和二进制数据中举行相互转换。
有了string范例转换的相干基本,读者就可以在以后的WebSocket举行二进制数据通报时明白相干的内容和处置惩罚逻辑。
下一篇WebSocket系列相干的博客,将会引见怎样经由历程WebSocket来向后端通报二进制数据,以及怎样处置惩罚经由历程WebSocket收到的二进制数据。有兴致的同砚可以继承关注。

    原文作者:hjava
    原文地址: https://segmentfault.com/a/1190000014087337
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞