资讯专栏INFORMATION COLUMN

WebSocket系列之字符串如何与二进制数据间进行互相转换

stackfing / 2220人阅读

摘要:总结通过使用和,我们能够在数据和二进制数据中进行互相转换。下一篇系列相关的博客,将会介绍如何通过来向后端传递二进制数据,以及如何处理通过收到的二进制数据。

概述

上一篇博客我们说到了如何进行数字类型(如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收到的二进制数据。有兴趣的同学可以继续关注。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93842.html

相关文章

  • WebSocket系列进制数据设计传输

    摘要:本文作为系列的第四篇内容,将会用一个简单的聊天应用把整个传输二进制数据类型的内容连接起来,让用户对整个传输二进制数据的方法有个了解。如何发送二进制数据通过如何设计一个二进制协议一章,我们知道了如何定义传输的二进制数据格式。 概述 通过前三篇博客,我们能够了解在通过WebSocket发送数据之前,我们需要传递的数据是如何变成ArrayBuffer二进制数据的;在我们收到二进制数据之后,我...

    amc 评论0 收藏0
  • WebSocket系列基础知识入门篇

    摘要:概述本文是系列的第一篇,主要介绍相关的基础协议知识和。客户端收到响应后,立即发起下一次的请求。收到消息通过事件来接收消息。类型则需要传递一个对象作为参数,相关的内容也将在本系列第二篇中进行介绍。 概述 本文是WebSocket系列的第一篇,主要介绍WebSocket相关的基础协议知识和API。由于WebSocket的相关介绍在MDN中分布较乱,初学者不太容易入门,因此通过本文将相关基础...

    Yuqi 评论0 收藏0
  • WebSocket系列如何建立和维护可靠的连接

    摘要:与此同时,后端服务的中也有相关的长连接维持时长设置。如何快速的恢复连接根据上面的操作方案,我们会在网络异常时断开连接。 概述 通过前四篇博客,相信读者对于WebSocket的使用和数据(不论是ArrayBuffer还是String)传输都有了一个深刻的了解。现在我们来介绍下,我在使用WebSocket时,连接相关模块遇到的一些共性问题,以及我们如何解决这些问题。 本文作为WebSock...

    BetaRabbit 评论0 收藏0
  • JavaScript如何实现UTF-16编码转换为UTF-8编码——utfx.js源码解析

    摘要:编码转换为编码下面让我们来看下如何将编码的数据转换为编码的数据。该方法是将码进行编码转换,从而得到编码的数据。 概述 当你在前端需要通过二进制数据与服务端进行通信时,你可能会遇到二进制数据的编码问题。大部分服务端的字符串编码类型都为UTF-8,而JavaScript中字符串编码类型是UTF-16,因此,你需要一个能够将字符串在两种编码方式间进行转换的方法。 本文通过对utfx.js这个...

    maybe_009 评论0 收藏0
  • WebSocket系列JavaScript中数字数据如何转换进制数据

    摘要:以和为例,说明中的数字数据如何转换为二进制数据。对象用来表示通用的固定长度的原始二进制数据缓冲区。中的数字数据如何转换为二进制数据对和有了一个大概的了解,下面让我们来看下它是如何进行二进制数据操作的。 概述 本文主要通过对JavaScript中数字数据与二进制数据之间的转换,让读者能够了解在JavaScript中如何对数字类型(包括但不限于Number类型)进行处理。 二进制数据在日常...

    MASAILA 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<