Szukaj…


Uwagi

Tablice maszynowe zostały pierwotnie określone w szkicu redaktora Khronos , a następnie znormalizowane w ECMAScript 6 §24 i §22.2 .

Obiekty BLOB są określone przez roboczą wersję roboczą interfejsu API pliku W3C .

Konwertowanie między obiektami BLOB i ArrayBuffers

JavaScript ma dwa podstawowe sposoby reprezentowania danych binarnych w przeglądarce. ArrayBuffers / TypedArrays zawierają zmienne (choć wciąż o stałej długości) dane binarne, którymi można bezpośrednio manipulować. Obiekty blob zawierają niezmienne dane binarne, do których można uzyskać dostęp tylko poprzez asynchroniczny interfejs pliku.

Konwertuj obiekt Blob na ArrayBuffer (asynchroniczny)

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

Konwertuj obiekt Blob do ArrayBuffer za pomocą Promise (asynchronicznie)

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.");
});

Konwertuj ArrayBuffer lub tablicę wpisaną na obiekt Blob

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

var blob = new Blob([array]);

Manipulowanie ArrayBuffers za pomocą DataViews

DataViews zapewniają metody odczytu i zapisu poszczególnych wartości z ArrayBuffer, zamiast przeglądania całej rzeczy jako tablicy jednego typu. Tutaj ustawiamy dwa bajty osobno, a następnie interpretujemy je razem jako 16-bitową liczbę całkowitą bez znaku, najpierw big-endian, a następnie 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

Tworzenie tablicy TypedArray z ciągu 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);
}

Korzystanie z tablic TypedArrays

TypedArrays to zestaw typów zapewniających różne widoki na zmienne binarne ArrayBuffers o stałej długości. W większości zachowują się jak tablice, które wymuszają przypisanie wszystkich wartości do danego typu liczbowego. Można przekazać instancję ArrayBuffer do konstruktora TypedArray, aby utworzyć nowy widok jego danych.

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 można kopiować przy użyciu metody .slice(...) , bezpośrednio lub poprzez widok 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]

Uzyskiwanie binarnej reprezentacji pliku obrazu

Ten przykład jest inspirowany tym pytaniem .

Zakładamy, że wiesz, jak załadować plik za pomocą interfejsu API plików .

// 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

Teraz wykonujemy faktyczną konwersję danych pliku na 1 i 0 za pomocą 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 umożliwia odczyt / zapis danych numerycznych; getInt8 konwertuje dane z pozycji bajtu - tutaj 0 , przekazywana wartość - w ArrayBuffer na 8-bitową reprezentację liczb całkowitych ze ArrayBuffer , a toString(2) konwertuje 8-bitową liczbę całkowitą na format reprezentacji binarnej (tj. ciąg 1 i 0).

Pliki są zapisywane jako bajty. Wartość przesunięcia „magicznego” jest uzyskiwana przez zauważenie, że bierzemy pliki przechowywane jako bajty, tj. Jako 8-bitowe liczby całkowite i odczytujemy je w 8-bitowej reprezentacji liczb całkowitych. Gdybyśmy próbowali odczytać nasze zapisane bajty (tj. 8 bitów) na 32-bitowe liczby całkowite, zauważylibyśmy, że 32/8 = 4 to liczba przestrzeni bajtów, która jest naszą wartością przesunięcia bajtu.


W przypadku tego zadania DataView ma nadmiar. Są one zwykle stosowane w przypadkach, w których napotyka się endianizm lub niejednorodność danych (np. Podczas odczytywania plików PDF, które mają nagłówki zakodowane w różnych bazach i chcielibyśmy w sposób znaczący wyodrębnić tę wartość). Ponieważ chcemy tylko reprezentacji tekstowej, nie dbamy o heterogeniczność, ponieważ nigdy nie ma takiej potrzeby

O wiele lepsze - i krótsze - rozwiązanie można znaleźć, stosując UInt8Array typu UInt8Array , która traktuje cały ArrayBuffer jako złożony z 8-bitowych liczb całkowitych bez znaku:

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

Iterowanie po tablicy Bufor

Aby w wygodny sposób iterować przez arrayBuffer, możesz utworzyć prosty iterator, który implementuje metody DataView pod maską:

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;
});

Następnie możesz utworzyć iterator taki:

var cursor = new ArrayBufferCursor(arrayBuffer);

Możesz użyć hasNext aby sprawdzić, czy są jeszcze elementy

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

Możesz użyć next metody, aby przyjąć następną wartość:

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

Przy takim iteratorze pisanie własnego parsera do przetwarzania danych binarnych staje się dość łatwe.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow