Buffer && View

又要報告ㄖ,該報告什麼呢QQ

機智的我決定來逛逛 NTCH

哦哦一年前的我寫的但沒很懂只是把 這篇 的說明步驟做一做而且最後其實算是小白寫出來的

重新研究了一下

覺得這可以喔

Why we need Buffer && View ?

Defination

Buffer: It represents a fixed-size chunk of contagious memory (binary data), can't directly access or modify

View: Interpreting binary data in Buffer from different perspectives,  the way we manipulate Buffer

In ES6

Buffer:  ArrayBuffer

View:  

 

// Allocate 2 bytes, the initial value is 0
const buffer = new ArrayBuffer(2) 
// 00000000 00000000
  • TypedArray (Uint8Array, Uint16Array......)
  • DataView
const u8 = new Uint8Array(2)
// 00000000 00000000
// => Uint8Array(2) [0, 0]

8 bit  = 1 byte

View:  

 

  • TypedArray (Uint8Array, Float64Array......)
  • DataView
const u8 = new Uint8Array(2)
// 00000000 00000000
// => Uint8Array(2) [0, 0]

On the data of ArrayBuffer, set up a layer of Array API that can access the data

View:  

 

  • TypedArray (Uint8Array, Float64Array......)
  • DataView
const u8 = new Uint8Array(2)
// 00000000 00000000
// => Uint8Array(2) [0, 0]
const u8 = new Uint8Array(2)
// 00000000 00000000 -> 8 bits a count
// => Uint8Array(2) [0, 0]

const u16 = new Uint16Array(u8.buffer)
// 0000000000000000 -> 16 bits a count
// => Uint16Array(2) [0]

We can decide how to read the binary data by different TypeArray

If Overflow......

Discard overflowing high bits

Uint8ClampedArray

Uint8Array.of(0xff, 0x100)
// Unit8Array [255, 0]
Uint8Array.of(0xff, 0x100, -100)
// Unit8Array [255, 0, 156]
Uint8ClampedArray.of(0xff, 0x100, -100)
// Uint8ClampedArray [255, 255, 0]

Why we need Buffer && View ?

Why we need Buffer && View ?

Manipulate Binary Data

Why don't we use Array ?

Array

ArrayBuffer

contain types

binary

number, string, array......

memory-use

fixed-size

dynamic

ArrayBuffer take less space when the exact data format is known, allows you to move more exactly through your data and gives the compiler/interpreter greater options for optimization.

Why don't we use Array ?

Use Case

  • WebGL
  • Canvas
  • Fetch API
  • FILE API
  • WebSockets
  • XMLHttpRequest
function getFileMagicNumber(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    
    reader.readAsArrayBuffer(file);
    reader.onerror = reject;

    reader.onload = () => {
      const uintArray = new Uint8Array(reader.result);

      const bytes = uintArray
        .slice(0, 4)
        .reduce((accumBytes, byte) => [...accumBytes, byte.toString(16).padStart(2, '0')], [])
        .join('')
        .toUpperCase();

      resolve(bytes);
    };
  });
}
function getFileMagicNumber(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    
    reader.readAsArrayBuffer(file);
    reader.onerror = reject;

    reader.onload = () => {
      const uintArray = new Uint8Array(reader.result);

      const bytes = uintArray
        .slice(0, 4)
        .reduce((accumBytes, byte) => [...accumBytes, byte.toString(16).padStart(2, '0')], [])
        .join('')
        .toUpperCase();

      resolve(bytes);
    };
  });
}

check MIME type

use the FileReader to read the first four bytes of a file to determine the MIME type of the file.

// fileTypes.js

export const IMAGE_PNG = '89504E47';

export const IMAGE_GIF = '47494638';

export const APPLICATION_PDF = '25504446';

....

Hex signature (wiki)

function getFileMagicNumber(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    
    reader.readAsArrayBuffer(file);
    reader.onerror = reject;

    reader.onload = () => {
      const uintArray = new Uint8Array(reader.result);

      const bytes = uintArray
        .slice(0, 4)
        .reduce((accumByte, byte) => [...accumByte, byte.toString(16).padStart(2, '0')], [])
        .join('')
        .toUpperCase();

      resolve(bytes);
    };
  });
}

check MIME type

use the FileReader to read the first four bytes of a file to determine the MIME type of the file.

// fileTypes.js

export const IMAGE_PNG = '89504E47';

export const IMAGE_GIF = '47494638';

export const APPLICATION_PDF = '25504446';

....
export default function checkFileTypes(file, allowTypes = []) {
  return new Promise(async (resolve, reject) => {
    const magicNumber = await getFileMagicNumber(file);

    if (!~allowTypes.flat().indexOf(magicNumber)) {
      reject(new Error('Invalid File Type'));
    }

    resolve();
  });
}
function getFileMagicNumber(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    
    reader.readAsArrayBuffer(file);
    reader.onerror = reject;

    reader.onload = () => {
      const uintArray = new Uint8Array(reader.result);

      const bytes = uintArray
        .slice(0, 4)
        .reduce(
          (accumBytes, byte) => [...accumBytes, byte.toString(16).padStart(2, '0')]
          , [])
        .join('') 
        .toUpperCase();

      resolve(bytes);
    };
  });
}
reader.onload = () => {
  const uintArray = new Uint8Array(reader.result);

  const bytes = uintArray
  .slice(0, 4)
  .reduce(
    (accumBytes, byte) => [...accumBytes, byte.toString(16).padStart(2, '0')]
    , [])
  .join('')
  .toUpperCase();

  resolve(bytes);
};
reader.onload = () => {
  const uintArray = new Uint8Array(reader.result);

  const bytes = uintArray
  .slice(0, 4)
  .reduce(
    (accumBytes, byte) => [...accumBytes, byte.toString(16).padStart(2, '0')]
    , [])
  .join('')
  .toUpperCase();

  resolve(bytes);
};

odd number of bytes

Why can't I use other TypedArray🤔

reader.onload = () => {
  const uintArray = new Uint8Array(reader.result);

  const bytes = uintArray
  .slice(0, 4)
  .reduce(
    (accumBytes, byte) => [...accumBytes, byte.toString(16).padStart(2, '0')]
    , [])
  .join('')
  .toUpperCase();

  resolve(bytes);
};

cause Array can contain String

TypedArray

hexadecimal

[137, 80. 78, 71]  base 10

  [89, 50, 4e, 29]   base 16

one more thing

可4下下禮拜又我 算惹

  • ASCII, UTF8, UTF16, UTF32
  • Endianness
  • TypedArray && DataView

Buffer and View

By Jay Chou

Buffer and View

  • 292