Анализ ArrayBuffer, TypedArray и Buffer

Node.js

предисловие

После обращения к node вы неизбежно будете оперировать файлами, поэтому можете столкнуться со следующими проблемами:

  • При написании заголовка запроса есть атрибут, называемый типом возвращаемых данных ответа (responseType), который поддерживает значение"arrayBuffer",ЭтоarrayBufferЧто тогда?
  • При обработке файлов в узле мы часто сталкиваемсяbuffer. такие как использованиеfs.readFile()При чтении файла тип первого параметра может бытьBuffer,ЭтоBufferЧто тогда?
  • В официальном документе о введении узла в Buffer упоминается очень важная вещь.TypedArray,ЭтоTypedArrayЧто это такое?

Если вы знаете ответы на эти три вопроса наизусть, то следующую статью можно пропустить. Если у вас есть какие-то сомнения, вы можете посмотреть вниз, возможно, это поможет вам решить проблему.

двоичный массив

Прежде всего, вам нужно понять двоичный массив, что очень важно для нас, чтобы понять три вышеперечисленные проблемы.

Что есть: Класс для работы с бинарными данными.

Почему существует:javaScriptПри обмене данными с графической картой большой объем данных в режиме реального времени необходимо форматировать в текстовом формате, тогда как двоичный формат экономит время преобразования.

Связь с массивом:bufferЭкземпляр подобен массиву целых чисел, ноbufferразмер фиксированный.

Двоичные массивы состоят из трех типов объектов:

  1. Объект ArrayBuffer: Представляет часть двоичных данных в памяти. Он не может напрямую управлять самой памятью и должен управляться через «представление». «Вид» развертывает интерфейс массива, что означает, что памятью можно управлять с помощью методов массива.
  2. Представление TypedArray: включает в общей сложности 9 типов представлений, таких какUint8Array(беззнаковое 8-битное целое) представление массива,Int16Array(16-битное целое) представление массива,Float32Array(32-битная с плавающей точкой) массив зрения и тому подобное.
  3. Представление данных: можно настроить вид составного формата, например, первый байт — Uint8 (беззнаковое 8-битное целое), второй и третий байты — Int16 (16-битное целое), а четвертый байт начинается с Float32 (32 числа с плавающей запятой) и т. д., и вы также можете настроить порядок следования байтов.

Волна жестких ответов:

  • ArrayBufferОбъекты представляют необработанные двоичные данные
  • TypedArrayПредставления используются для чтения и записи простых типов двоичных данных (ArrayBuffer),DataViewПредставления используются для чтения и записи сложных типов двоичных данных (ArrayBuffer).
  • в узлеBufferКлассы реализованы более оптимизированным и удобным для Nodejs способом.Uint8ArrayAPI, что означаетBufferкласс на самом делеTypedArray(Uint8Array)Реализация nodejs.

На данный момент должны быть решены указанные выше три проблемы. Чтобы узнать больше, продолжайте читать.

ArrayBuffer

ArrayBufferОбъект представляет собой часть памяти, в которой хранятся двоичные данные. Он не может быть напрямую прочитан или записан, но им можно манипулировать только через представления.

ArrayBufferЭто также конструктор, который выделяет часть непрерывной памяти для хранения данных.

const buffer = new ArrayBuffer(12); // 生成一个可以12个字节的连续内存,每个字节的默认值是0

Читать как представление DataView

const buffer = new ArrayBuffer(12);
const dataView = new DataView(buffer); // 对一段12字节的内存建立DataView视图
dataView.getUint8(0); // 0 以Uint8方式读取第一个字节

Чтение в представлении TypedArray.В отличие от DataView, DataView — это конструктор, а TypedArray — набор конструкторов.

const buffer = new ArrayBuffer(12);
const x1 = new Uint8Array(buffer); // 建立Uint8Array视图
const x2 = new Int32Array(buffer); // 建立Int32Array视图
x1[0] = 1;
x2[0] = 2;
// 由于两个视图是对应的是同一段内存,所以其中一个视图更改了内存,会影响到另一个视图
x1[0]; // 2

Объекты ArrayBuffer также имеют свойство byteLength и метод среза (этот метод является единственным методом объекта ArrayBuffer, который может считывать и записывать память).

ArrayBuffer имеет статический метод isView, который определяет, является ли параметр экземпляром представления.

const buffer = new ArrayBuffer(12);
buffer.byteLength; // 12
buffer.slice(0, 3); // 用法和数组一致,拷贝buffer的前三个字节生成一个新的ArrayBuffer对象
ArrayBuffer.isView(buffer); // false
const dataView = new DataView(buffer);
ArrayBuffer.isView(dataView); // true
составной вид

Поскольку конструктор представления может указывать начальную позицию и длину, различные типы данных могут храниться последовательно в одном и том же сегменте памяти, что называется «составным представлением».

const buffer = new ArrayBuffer(12);
const a = new Uint8Array(buffer, 0, 1); // 以Uint8Array读取第一个字节
a[0] = 1;
const b = new Int32Array(buffer, 1, 2); // 以Int32Array读取第二个字节
b[0] = 2;

Посмотреть

Что такое представление: объекты ArrayBuffer могут хранить множество типов данных. Разные типы данных имеют разную интерпретацию, это называется представлением.

Роль представления: интерпретировать двоичные данные в указанном формате.

TypedArray

TypedArray содержит в общей сложности девять типов, каждый из которых является конструктором. (представление DataView поддерживает восемь, кроме Uint8ClampedArray)

имя Занятые байты описывать
Int8Array 1 8-битное целое число со знаком
Uint8Array 1 8-битное целое число без знака
Uint8ClampedArray 1 Фиксированный массив 8-битных целых чисел без знака (значение от 0 до 255)
Int16Array 2 16-битное целое число со знаком
Uint16Array 2 16-битное целое число без знака
Int32Array 4 32-битное целое число со знаком
Uint32Array 4 32-битное целое число без знака
Float32Array 4 32-битная IEEE с плавающей запятой
Float64Array 8 64-битный IEEE с плавающей запятой
приемлемые параметры
  • Конструктор представления принимает три параметра: первый объект ArrayBuffer, номер байта начала второго представления (0 по умолчанию) и номер байта конца третьего представления (по умолчанию до конца этой памяти). площадь)
  • приниматьArrayBuffer реальныйПример в качестве параметра для чтения двоичных данных в указанном формате
  • приемлемонормальный массивВ качестве параметра сразу выделяем память для генерации экземпляра ArrayBuffer, и заодно присваиваем значения этой памяти, а затем генерируем представление на основе этой памяти.
  • приемлемоПосмотретьВ качестве параметра генерируется новый массив, который копирует значения представления параметра, создавая новый массив и представление. (Чтобы сгенерировать новое представление на основе той же памяти, вам нужно передать view.buffer)
отличие от массива
  • Члены внутри TypedArray могут быть только одного типа
  • Члены TypedArray являются смежными и не будут иметь вакансий
  • Член TypedArray по умолчанию равен 0, по умолчанию это пустой массив.
  • TypedArray — это просто представление и не хранит данные сами по себе. Данные хранятся в базовом массиве ArrayBuffer. Чтобы получить базовый объект, необходимо использовать свойство буфера.
  • TypedArray может напрямую манипулировать памятью без преобразования типов, поэтому он быстрее, чем массив.
  • Некоторые методы массива TypedArray можно использовать, но нельзя использоватьcancatметод

DataView

Если часть данных содержит несколько типов данных, помимо использования составного представления для чтения, вы также можете использовать представление DataView для чтения.

DataViewВид обеспечивает более эксплуатационные параметры и поддерживает настройку последовательности слов. Первоначально, в дизайнерских целях,ArrayBufferРазличные объектыTypedArrayПредставление используется для передачи данных на локальные устройства, такие как сетевые карты и звуковые карты, поэтому можно использовать порядок байтов локального компьютера; иDataViewНазначением представления является обработка данных, отправляемых сетевым устройством, поэтому порядок байтов с прямым порядком байтов или прямым порядком байтов можно установить самостоятельно.

Порядок байтов с прямым порядком байтов и прямым порядком байтов, все компьютеры системы x86 используют порядок байтов с прямым порядком байтов, 12 в 123456 более важно, поэтому он находится сзади, а порядок хранения - 563412. Большой порядок байтов противоположен

  • Ряд методов get используется для чтения памяти.

    const buffer = new ArrayBuffer(24);
    const dv = new DataView(buffer);
    // 接受一个参数
    const v1 = dv.getUint8(0); // 从第一个字节读取一个8位无符号整数
    // 读两个字节以上时,需要明确数据的存储模式(true:小端/false:大端)
    const v1 = dv.getUint16(1, true); // 从第二个字节开始,读取一个16位无符号整数(长度两个字节)
    
  • Некоторые методы набора столбцов используются для записи в память.

    // 接受三个参数,1.字节序号,2.写入的数据,3.写入方式(true:小端/false|undeifined:大端)
    dv.setInt32(0, 25, false); // 在第一个字节以大端字节序写入一个值为25的32位整数
    

Буферы в узле

До введения TypedArray в js не было механизма для чтения или управления потоками двоичных данных. Класс Buffer был представлен как часть API nodejs для взаимодействия с потоками октетов в потоках TCP, файловой ОС и контекстах.

теперь доступноTypedArray,BufferКлассы реализованы более оптимизированным и удобным для Node.js способом.Uint8ArrayAPI.

Экземпляры класса буфера похожи на массивы целых чисел от 0 до 255 (остальные целые числа передаются через& 255операция приводит к диапазону)

buffer.from()

  • buffer.from(array), возвращает новый буфер, содержащий копию данного массива октетов
  • buffer.from(buffer), возвращает новый буфер, содержащий копию данного буфера
  • buffer.from(arrayBuffer[ betyOffset[ len]]), возвращает новый Buffer, который использует ту же память, что и данный arrayBuffer
  • buffer.from(string), возвращает новый Buffer, содержащий копию данной строки
  • buffer.alloc(size), возвращает только что инициализированный буфер указанного размера
  • buffer.allocUnsafe(size)/buffer.allocUnsafeslow(size), возвращает новый неинициализированный (не очищенный) буфер указанного размера

Инициализация выполняется медленно, но она может гарантировать, что вновь созданный экземпляр буфера не содержит конфиденциальных данных.

Если размер меньше или равен половине buffer.poolsize, экземпляр буфера, сгенерированный allocUnsafe, может быть выделен из общего пула внутренней памяти, и allocUnsafeslow никогда не будет использовать общий пул внутренней памяти.

буфер и типизированный массив

  • Bufferэкземпляр такжеUint8Arrayэкземпляр, но сTypedArrayЕсть небольшие отличия. (буфер можно сравнить с просмотром)

  • Buffer.from()а такжеTypedArray.from()Есть разные реализации. В частности, typedArray.form() принимает второй параметр как функцию отображения, а buffer.form() — нет.

Справочная документация:

Ecmascript начинается --ArrayBuffer

Китайская сеть Node.js — буфер