Поиск…


замечания

Типизированные массивы были первоначально указаны в проекте редактора Khronos , а затем стандартизованы в ECMAScript 6 §24 и §22.2 .

Blobs заданы рабочим проектом W3C File API .

Преобразование между Blobs и ArrayBuffers

JavaScript имеет два основных способа представления двоичных данных в браузере. ArrayBuffers / TypedArrays содержат изменчивые (хотя и фиксированные) двоичные данные, с которыми вы можете напрямую манипулировать. Blobs содержат неизменяемые двоичные данные, доступ к которым возможен только через асинхронный интерфейс File.

Преобразование Blob в ArrayBuffer (асинхронный)

var blob = new Blob(["\x01\x02\x03\x04"]),
    fileReader = new FileReader(),
    array;

fileReader.onload = function() {
    array = this.result;
    console.log("Array contains", array.byteLength, "bytes.");
};

fileReader.readAsArrayBuffer(blob);
6

Преобразование Blob в ArrayBuffer с использованием Promise (асинхронный)

var blob = new Blob(["\x01\x02\x03\x04"]);

var arrayPromise = new Promise(function(resolve) {
    var reader = new FileReader();

    reader.onloadend = function() {
        resolve(reader.result);
    };

    reader.readAsArrayBuffer(blob);
});

arrayPromise.then(function(array) {
    console.log("Array contains", array.byteLength, "bytes.");
});

Преобразование ArrayBuffer или типизированного массива в Blob

var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]);

var blob = new Blob([array]);

Манипулирование массивами с помощью DataViews

DataViews предоставляют методы для чтения и записи отдельных значений из ArrayBuffer, а не для просмотра всего объекта как массива одного типа. Здесь мы устанавливаем два байта отдельно, а затем интерпретируем их вместе как 16-разрядное целое без знака, первое из которых является big-endian then little-endian.

var buffer = new ArrayBuffer(2);
var view = new DataView(buffer);

view.setUint8(0, 0xFF);
view.setUint8(1, 0x01);

console.log(view.getUint16(0, false)); // 65281
console.log(view.getUint16(0, true));  // 511

Создание TypedArray из строки Base64

var data = 
   'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACN' +
   'byblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHx' +
   'gljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';

var characters = atob(data);

var array = new Uint8Array(characters.length);

for (var i = 0; i < characters.length; i++) {
  array[i] = characters.charCodeAt(i);
}

Использование TypedArrays

TypedArrays - это набор типов, предоставляющих различные виды в изменяемые бинарные массивы ArrayBuffers с фиксированной длиной. По большей части они действуют как массивы, которые принуждают все назначенные значения к заданному числовому типу. Вы можете передать экземпляр ArrayBuffer в конструктор TypedArray для создания нового представления его данных.

var buffer = new ArrayBuffer(8);
var byteView = new Uint8Array(buffer);
var floatView = new Float64Array(buffer);

console.log(byteView);  // [0, 0, 0, 0, 0, 0, 0, 0]
console.log(floatView); // [0]
byteView[0] = 0x01;
byteView[1] = 0x02;
byteView[2] = 0x04;
byteView[3] = 0x08;
console.log(floatView); // [6.64421383e-316]

ArrayBuffers можно скопировать с использованием .slice(...) , либо напрямую, либо через представление TypedArray.

var byteView2 = byteView.slice();
var floatView2 = new Float64Array(byteView2.buffer);
byteView2[6] = 0xFF;
console.log(floatView);  // [6.64421383e-316]
console.log(floatView2); // [7.06327456e-304]

Получение двоичного представления файла изображения

Этот пример вдохновлен этим вопросом .

Предположим, вы знаете, как загрузить файл с помощью File API .

// preliminary code to handle getting local file and finally printing to console
// the results of our function ArrayBufferToBinary().
var file = // get handle to local file.
var reader = new FileReader();
reader.onload = function(event) {
    var data = event.target.result;
    console.log(ArrayBufferToBinary(data));
};
reader.readAsArrayBuffer(file); //gets an ArrayBuffer of the file

Теперь мы выполняем фактическое преобразование данных файла в 1 и 0 с помощью DataView :

function ArrayBufferToBinary(buffer) {
   // Convert an array buffer to a string bit-representation: 0 1 1 0 0 0...
   var dataView = new DataView(buffer);
   var response = "", offset = (8/8); 
   for(var i = 0; i < dataView.byteLength; i += offset) {
       response += dataView.getInt8(i).toString(2); 
   }
   return response;
}

DataView позволяет читать / записывать числовые данные; getInt8 преобразует данные из позиции байта - здесь 0 , значение, переданное в - в ArrayBuffer к подписанному 8-битовому целочисленному представлению, а toString(2) преобразует 8-разрядное целое в формат двоичного представления (то есть строку из 1 и 0 ').

Файлы сохраняются как байты. Значение «магического» смещения получается, если мы принимаем файлы, хранящиеся в байтах, т. Е. Как 8-битные целые числа и считываем их в 8-битном целочисленном представлении. Если бы мы пытались прочитать наши байтовые (т. Е. 8-битные) файлы в 32-битные целые числа, отметим, что 32/8 = 4 - это количество байтовых пробелов, которое является нашим значением смещения байта.


Для этой задачи DataView s излишне. Они обычно используются в случаях, когда встречаются сущность или неоднородность данных (например, при чтении PDF-файлов, которые имеют заголовки, закодированные в разных базах, и мы хотели бы осмысленно извлечь это значение). Поскольку нам просто нужно текстовое представление, мы не заботимся о гетерогенности, поскольку никогда не нужно

Решение гораздо лучше - и короче - можно найти с помощью массива, типизированного в UInt8Array , который обрабатывает весь ArrayBuffer как состоящий из 8-битных целых чисел без знака:

function ArrayBufferToBinary(buffer) {
    var uint8 = new Uint8Array(buffer);
    return uint8.reduce((binary, uint8) => binary + uint8.toString(2), "");
}

Итерация через массивBuffer

Для удобного способа итерации через arrayBuffer вы можете создать простой итератор, который реализует методы DataView под капотом:

var ArrayBufferCursor = function() {
  var ArrayBufferCursor = function(arrayBuffer) {
    this.dataview = new DataView(arrayBuffer, 0);
    this.size = arrayBuffer.byteLength;
    this.index = 0;
  }

  ArrayBufferCursor.prototype.next = function(type) {
    switch(type) {
      case 'Uint8':
        var result = this.dataview.getUint8(this.index);
        this.index += 1;
        return result;
      case 'Int16':
        var result = this.dataview.getInt16(this.index, true);
        this.index += 2;
        return result;
      case 'Uint16':
        var result = this.dataview.getUint16(this.index, true);
        this.index += 2;
        return result;
      case 'Int32':
        var result = this.dataview.getInt32(this.index, true);
        this.index += 4;
        return result;
      case 'Uint32':
        var result = this.dataview.getUint32(this.index, true);
        this.index += 4;
        return result;
      case 'Float':
      case 'Float32':
        var result = this.dataview.getFloat32(this.index, true);
        this.index += 4;
        return result;
      case 'Double':
      case 'Float64':
        var result = this.dataview.getFloat64(this.index, true);
        this.index += 8;
        return result;
      default:
        throw new Error("Unknown datatype");
    }
  };

  ArrayBufferCursor.prototype.hasNext = function() {
    return this.index < this.size;
  }

  return ArrayBufferCursor;
});

Затем вы можете создать итератор следующим образом:

var cursor = new ArrayBufferCursor(arrayBuffer);

Вы можете использовать hasNext чтобы проверить, есть ли еще элементы

for(;cursor.hasNext();) {
    // There's still items to process
}

Вы можете использовать next метод для следующего значения:

var nextValue = cursor.next('Float');

С таким итератором писать собственный парсер для обработки двоичных данных становится довольно легко.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow