Как преобразовать между строками JavaScript серии WebSocket и двоичными данными

задняя часть JavaScript WebSocket Unicode

Обзор

В прошлом блоге мы говорили о том, как выполнить бинарное преобразование числовых типов (таких как Short, Int и Long) в JavaScript, Если вам интересно, вы можете прочитать второй блог из этой серии —Как преобразовать цифровые данные в двоичные данные в JavaScript в серии WebSocket. На этот раз поговорим о том, как работать с данными строкового типа. Эта статья является третьей частью серии WebSocket. В ней в основном представлен метод преобразования между строковыми данными и двоичными данными. Конкретное содержание выглядит следующим образом:

  • Базовые знания строкового типа в JavaScript.
  • Как преобразовать строковый тип в двоичные данные в JavaScript
  • JavaScript如何将二进制数据转换为string类型 Эта статья не слишком тесно связана с WebSocket, но как базовая база знаний для передачи двоичных данных в WebSocket включена в эту серию. 如果读者对WebSocket并不了解,或者说不明白它的使用场景和细节,可以阅读我的本系列的第一篇博客——Введение в базовые знания серии WebSocket.

Базовые знания о типах строк

Этот тип строки должен быть знаком учащимся, знакомым с JavaScript, так как это один из основных типов данных в JavaScript. Однако сегодня мы собираемся представитьDOMString.

DOMString — это строка UTF-16. Так как JavaScript уже использует такие строки, DOMString напрямую сопоставляется со строкой. Передача null методу или параметру, который принимает DOMString, обычно преобразует его в «null».

При выполнении передачи данных строкового типа в WebSocket фактически используетсяDOMString. Однако, согласноMDNсредняя параDOMStringИз введения мы можем понять, что в большинстве сценариев повседневного использования мы можем думать, чтоDOMStringявляется строковым типом. Следовательно, нам нужно только понять этот тип и по-прежнему обращаться с ним как со строковым типом при его использовании.

кодирование

Поскольку выше упоминалась UTF-16, давайте кратко представим UTF-16 и UTF-8, которые обычно используются в бэкэнде. Зачем нам нужно вводить типы кодирования? Потому что мы можем использовать разные методы кодирования при передаче строковых данных с серверной частью, что приведет к тому, что две стороны получат разные данные. Поэтому, когда мы передаем двоичные данные строки, нам нужно не только преобразовать строку в двоичную, но также требуется согласованная кодировка строки.

UTF-16

UTF-16 (16-битный формат преобразования Unicode) — это третий уровень пятиуровневой модели кодирования символов Unicode: реализация формы кодирования символов (форма кодирования символов, также известная как «формат хранения»). То есть абстрактные кодовые точки набора символов Unicode отображаются в последовательность 16-битных целых чисел (т. е. единиц кода) для хранения или передачи данных. Кодовая точка символа Unicode требует для представления одной или двух 16-битных кодовых единиц, поэтому это представление переменной длины.

UTF-16 — это тип кодировки строк в JavaScript.

UTF-8

UTF-8 (8-битный формат преобразования Unicode) — это кодировка символов переменной длины для Unicode и код префикса. Его можно использовать для представления любого символа стандарта Unicode, и первый байт в его кодировке по-прежнему совместим с ASCII, что позволяет продолжать использовать исходное программное обеспечение, обрабатывающее символы ASCII, без модификаций или с некоторыми изменениями. UTF-8 кодирует каждый символ с использованием от одного до четырех байтов (перенормировано в ноябре 2003 г.).

UTF-8 — это распространенный тип кодировки, используемый многими языками и очень распространенный в серверных приложениях.

Как преобразовать кодировку UTF16 и UTF-8 в JavaScript

На Github есть библиотека конвертацииGitHub - dcodeIO/utfx: A compact library to encode, decode and convert UTF8 / UTF16 in JavaScript.

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 в строковые данные UTF-16.
  • calculateUTF16asUTF8, рассчитайте длину в байтах, занимаемую типом строки в кодировке UTF-16, преобразованной в UTF-8. Мы будем использовать эти два метода в последующих главах.

Как преобразовать строковый тип в двоичные данные в JavaScript

Зная кодировку строкового типа в JavaScript и способ преобразования кодировки между UTF-8 и UTF-16, давайте посмотрим, как преобразовать строковый тип в двоичные данные. Прежде всего, мы предполагаем, что при взаимодействии с бэкендом используется кодировка 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 байта двоичного заголовка.

Как JavaScript преобразует двоичные данные в строковый тип

Зная, как преобразовать строковый тип в двоичные данные, давайте посмотрим, как прочитать все данные из двоичного и обратно преобразовать в строковый тип. В соответствии с описанным выше процессом преобразования в двоичный, нам нетрудно подумать о методах, связанных с двоичным и строковым типами. Конкретные примеры следующие:

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 байтах, а затем прочитать кодировку символов строки с указанной длиной с позиции 4-го байта (считая с 0) , Вот и все. Наконец, мы получаем массив кодов Unicode, просто нужноfromCharCodeметод преобразования его в строку.

Суммировать

Используя ArrayBuffer и DataView, мы можем преобразовывать строковые данные в двоичные. С соответствующей основой преобразования типа строки читатели могут понять соответствующий контент и логику обработки, когда WebSocket будет выполнять передачу двоичных данных в будущем. В следующем блоге из серии WebSocket будет рассказано, как передавать двоичные данные в серверную часть через WebSocket и как обрабатывать двоичные данные, полученные через WebSocket. Заинтересованные студенты могут продолжать обращать внимание.