ECMAScriptでのバイナリ相互変換メモ

# 概要
Blob！base64！ArrayBuffer！typedArray！
色々表現があって混乱するけど、内容はどれもバイナリだろうし、行ったりきたりできるようにしたいなぁの記事

## それぞれの型の紹介
### 早見表
|            | MIME |索引| バイナリサイズ|
|:-----------|:----:|:--:|:-----------:|
| Blob       | o    |x   |blob.size    |
| TypedArray | x    |o   |ta.byteLength|
| ArrayBuffer| x    |x   |ab.byteLength|
| base64     | △   |x   |x            |

### Blob
Binary Large Objectの略。MIME情報を保持する。各要素はアクセスできないがsliceはできる

#### BlobURL
BlobURLと呼ばれるリンクを作ることもできる。これはbase64のように生情報を保持するのではなく、ブラウザがメモリへの参照を用意してくれるようなもの。
`blob:https?://{domain}/{UUID}`みたいな値になります。
ブラウザが起動している時だけ生きているので、ここにリンクを張ってどうのこうのみたいなことはできないが、キャッシュが仕事をしやすいため、繰り返し参照するような場合は後述のbase64より使い勝手が良いだろう


[Blob - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/Blob)

### TypedArray
型付き配列。

- Int8Array
- Uint8Array
- Uint8ClampedArray
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
- BigInt64Array
- BigUint64Array

[標準組み込みオブジェクト | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects)
たくさんあるね。バイト列として使われやすいのはおそらく`Uint8Array`
型が付いているだけで性質はArrayを継承しているので、`filter`とか`map`も使えるが、型の外の値は出力できないことに留意する


```js:typedarray2blob.js
   const blob = new Blob([typedArray], {type: MIME});
```
```js:blob2typedarray.js
const reader = new FileReader();
reader.addEventListener('loadend', () => {
   // reader.result には blob の内容が型付き配列として格納されます。
   console.log(reader.result);
});
reader.readAsArrayBuffer(blob);
const MIME = blob.type
```
### ArrayBuffer
物理メモリを確保するクラス。内部操作はできないので、viewと呼ばれるtypedarrayやDataViewで行う。
typedarrayで行う場合はエンディアンが動作環境依存であることに注意する。

```js:arraybuffer2typedarray.js
   const uint8 = new Uint8Array(arraybuffer);
```
```js:arraybuffer2typedarray.js
   const dataview =new DataView(arraybuffer);
```
[ArrayBuffer - JavaScript | MDN]
(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)
[DataView - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/DataView)

### バイナリデータ文字列
文字コード0xff以下の文字でできた文字列のことをとりあえずこう呼ぶことにする。
ASCIIでエンコードすれば(UTF-16・UTF-32以外の大抵はそうだと思うけど)、バイナリを表現しているに等しい。

```js:uint82bintxt.js
   const bintxt = String.fromCharCode(...uint8);
```
```js:bintxt2uint8.js
   const uint8 = new Uint8Array(Array.from(bintxt).map((c)=>c.charCodeAt()))
```

### base64
バイトデータを64進法で表記したもの。テキストに乗せてバイトデータをやり取りできる。
末尾にパディング`=`があるので厳密には65文字が利用される。
`data:{MIME};base64,{base64}`と表記することで、URIとして利用できる。

[base64 - MDN Web Docs](https://developer.mozilla.org/ja/docs/Glossary/Base64)

#### Bufferを使う方法
:::note warn
Node.js上でのみ動作します
:::
BufferはNode.js上で利用できるバイナリクラスです。ArrayBufferに似ていますが挙動が異なったりします

```js:buffer2base64.js
   const base64 = buf.toString("base64");
```
```js:base642bintxt.js
   const buffer = Buffer.from(base64, "base64");
```
#### btoa・atobを使う方法
:::note alert
この関数は、レガシーなウェブプラットフォームのAPIとの互換性のためにのみ提供されており、新しいコードでは決して使用しないでください。なぜなら、バイナリデータを表すために文字列を使用し、JavaScriptで型付き配列が導入されるよりも前のものだからです。Node.js APIを使用して実行されるコードでは、`Buffer.from(str, 'base64')` および `buf.toString('base64')` を使用してbase64エンコード文字列とバイナリデータ間の変換を実行する必要があります。
:::
とのことなので、ブラウザ上でのみ利用しましょう

btoa, atobでバイナリデータ文字列(文字コード0xff以下の文字でできた配列)とBase64が相互変換できる。aはascii(=base64), bは(文字表現の)binaryです。 ~~わかりにくっ~~


```js:bintxt2base64.js
   const base64 = btoa(bintxt);
```
```js:base642bintxt.js
   const bintxt = atob(base64);
```

[btoa() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/btoa)
#### FileReaderを利用する方法
filereaderを利用することで，blobからbase64を得る方法もあります

```js:blob2base64.js
const blob2base64 = (blob) => Promise((resolve)=>{
  const reader = new FileReader();
  reader.onload = (e) => {
    resolve(event.target.result);
  }
  reader.readAsDataURL(blob);
});
const base64 = await blob2base64(blob);
```

# まとめ
これらを組み合わせればとりあえず相互変換ができると思います。
`blob<==>uint8<==>bintxt<==>base64`
`arraybuffer==>typedarray`

サンプルコードはスッキリ度重視で選んだので、パフォーマンスに不満を感じる場合はうまく書き換えてください