js 二进制相关知识
buffer
- ArrayBuffer 纯粹的原始二进制内存(裸内存块),只负责存储
- Uint8Array / Uint16Array / DataView 操作内存的视图,站在 ArrayBuffer 之上的读取/写入方式
- Uint8Array 每 1 个字节一个无符号整数
- Uint16Array 每 2 个字节一个无符号整数
- DataView 允许你按任意偏移、任意类型去读写底层内存
- Buffer 是 nodehjs中 Uint8Array 子类,一种增强实现
Node 先自己搞出了一套 Buffer
后来 web平台标准化 ArrayBuffer,Uint8Array...等
Node 为了和 web 平台更一致,也增加了对 ArrayBuffer,Uint8Array...等的支持
Blob / File (字节数据对象层)
- Blob
- 一段二进制数据的高层封装对象
- 一个不可变的二进制数据包
- File 带文件元数据的 Blob
Blob
- 浏览器里的一个二进制大对象(Binary Large Object)
- 里面装的是一段原始数据
- 这段数据可以是文本、图片、音频、视频、任意 bytes
- 它有 type(MIME 类型)
- 它本身是不可变的
Blob 我现在手里有一坨二进制内容,
我希望把它当作一个完整对象来传递、切片、读取、下载。
File
- 带名字的
- 带修改时间的
- 可读取内容的
- 看起来像文件的二进制对象
URL.createObjectURL() / revokeObjectURL()
- 把内存里的 Blob/File,映射成一个浏览器可消费的临时 URL。
js
const url = URL.createObjectURL(blob)
img.src = url
a.href = urlFileReader
- 历史上很重要,现在已经没有那么核心了
- 以前
- readAsText / readAsArrayBuffer /readAsDataURLjs
const input = document.querySelector('#file') as HTMLInputElement input.addEventListener('change', () => { const file = input.files?.[0] if (!file) return const reader = new FileReader() reader.onload = () => { console.log('文本内容:', reader.result) // string } reader.onerror = () => { console.error('读取失败:', reader.error) } reader.readAsText(file, 'utf-8') })
- readAsText / readAsArrayBuffer /readAsDataURL
- 现在
- blob.text() / blob.arrayBuffer() / blob.stream()js
const file = input.files?.[0] if (!file) return const text = await file.text() console.log(text)
- blob.text() / blob.arrayBuffer() / blob.stream()
- FileReader 仍然有价值的场景
- readAsDataURL() / URL.createObjectURL()
- readAsDataURL() 本地图片显示,是把文件内容真的读出来,再转成一个很长的 data: base64 字符串
- URL.createObjectURL() 生成一个浏览器内部可访问的临时 URL
- FileReader.readAsText(blob, encoding) / Blob.text()
- Blob.text() 总是按 UTF-8 解释
- FileReader.readAsText(blob, encoding) 可以指定编码
- readAsDataURL() / URL.createObjectURL()
TextEncoder / TextDecoder
- 字节世界与文本世界的转换
js
new TextEncoder().encode('hello') // Uint8Array
new TextDecoder().decode(uint8Array) // stringResponse / Request / fetch
js
// 底层数据源是一份,外层可以按不同抽象层读取。
const res = await fetch(url)
const ab = await res.arrayBuffer() // 裸字节内存
const blob = await res.blob() // 数据包对象
const text = await res.text() // 文本
const stream = res.body // 流atob / btoa 与 Base64
- Base64 不是二进制本体,而是“用文本表示二进制”的一种编码形式。
总结
- 内存线 ArrayBuffer -> TypedArray / DataView 字节在内存里怎么存在、怎么读写
- 对象分装线 Blob / File 怎么把一段字节包装成浏览器方便处理的对象
- 流动线 ReadableStream -> TransformStream -> WritableStream 数据不一次性全到,而是边读边处理边写