Преобразование части из байт в строку по длинне строки

Рейтинг: 1Ответов: 1Опубликовано: 23.07.2023

Есть ArrayBuffer, который читается через DataView

var arrayBuffer = (... получено с сервера)
var view = new DataView(arrayBuffer);

var offset = 0;

var stringLength = view.getUint8(offset); //длина строки является одним байтом
offset++;

var value = //прочитать строку из байт по её длине. (при этом в байтах останется ещё информация, которая не относится к строке)

То есть с сервера приходит длина строки, и за длиной идёт сама строка, и за строкой идёт ещё информация, например картинка. Взять длину строки как длину байт нельзя, ведь есть символы из нескольких байт. Клиент в браузере. Не NodeJS

Ответы

▲ 0Принят

Передавать байты в TextDecoder.decode по одному пока не накопится строка требуемой длины. Не самое быстрое решение, но показывает идею:

const encode = s => new TextEncoder().encode(s).buffer;

const decode = (buffer, n) => {
    const td = new TextDecoder();
    let s = '';
    for (let i = 0; i < buffer.byteLength; ++i) {
        s += td.decode(new DataView(buffer, i, 1), {stream: true});
        if (s.length >= n) {
            break;
        }
    }
    return s;
};

const test = (s, n) => {
    console.log();
    console.log('source', s);
    const b = encode(s);
    console.log('buffer', new Uint8Array(b));
    console.log('result', decode(b, n));
}

test('Hello!', 3);
test('Привет!', 3);

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

const decode = (buffer, start, n) => {
    const td = new TextDecoder();
    let s = '';
    let i = start;
    while (i < buffer.byteLength && s.length < n) {
        const len = Math.min(n - s.length, buffer.byteLength - i);
        s += td.decode(new DataView(buffer, i, len), {stream: true});
        i += len;
    }
    return [s, i];
};