1.1Nodejs和浏览器中的二进制处理
Buffer
在 Node.js 中,Buffer
类用于处理二进制数据。由于 JavaScript 在浏览器环境中主要用于处理字符串和数字等类型的数据,对二进制数据的处理能力较弱,因此 Node.js 引入了 Buffer
类来弥补这一不足,特别是在处理文件系统操作、网络流等方面时。
Buffer 的基本概念
- 固定大小:一旦创建,
Buffer
实例的大小是固定的,不能调整。 - 存储整数:每个
Buffer
实例都是一个包含 8 位无符号整数值(0 到 255)的数组。 - 高效性:设计用来高效地存储和操作二进制数据。
Buffer不指定编码,默认转换时是 uft8编码
创建 Buffer
-
从字符串创建
const buf = Buffer.from('hello', 'utf8');
-
从数组创建
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
-
分配指定大小的 Buffer
注意,直接使用
Buffer
构造函数或.allocUnsafe()
分配内存时不初始化内存,可能包含敏感数据,建议使用.alloc()
方法:const buf = Buffer.alloc(10); // 创建一个长度为 10,值全为 0 的 Buffer
操作 Buffer
-
读写数据
可以通过索引直接访问或修改
Buffer
中的数据:buf[0] = 0x62; // 修改第一个字节 console.log(buf[0]); // 读取第一个字节
-
转换
转换为其他格式如字符串:
const str = buf.toString('utf8');
其他常用方法
buf.length
: 获取 Buffer 的字节长度。buf.equals(otherBuffer)
: 检查两个 Buffer 是否相等。buf.compare(otherBuffer)
: 比较两个 Buffer,类似于字符串比较。buf.slice([start[, end]])
: 返回一个新的 Buffer,它与原 Buffer 共享相同的内存区域,但偏移量不同。buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])
: 将 Buffer 的一部分复制到另一个 Buffer。
注意事项
- 处理
Buffer
时需要特别小心,因为它们可以直接访问内存,不正确的使用可能导致安全问题或内存泄漏。 - 使用
Buffer
时应尽量避免使用未初始化的内存,即优先选择Buffer.alloc()
而不是Buffer.allocUnsafe()
。
Buffer
是 Node.js 中处理二进制数据的重要工具
浏览器中的二进制数据处理
在浏览器环境中,原生并不支持 Node.js 的 Buffer
类,因为 Buffer
是 Node.js 特有的用于处理二进制数据的类,主要用于服务器端开发。然而,在浏览器中,如果你需要处理二进制数据,可以使用 JavaScript 提供的几种内置对象和类型,例如 ArrayBuffer
、TypedArray
(如 Uint8Array
)和 Blob
等。
-
ArrayBuffer:一个固定长度的字节数组,不能直接操作其内容,而是通过视图(views)来读写数据。
-
TypedArray:包括
Int8Array
,Uint8Array
,Uint8ClampedArray
,Int16Array
,Uint16Array
,Int32Array
,Uint32Array
,Float32Array
, 和Float64Array
等,提供了以特定格式访问ArrayBuffer
数据的方法。 -
DataView:提供了一个底层接口,用于访问
ArrayBuffer
中的数据,允许以不同的格式读写数据。 -
Blob:代表不可变的、原始数据的类文件对象,基于输入的数据创建一个包含指定类型的二进制数据的对象。
-
TextEncoder 和 TextDecoder:用于在字符串与 Uint8Array 之间进行转换。(我们在base64编码里使用过.6.6js对base64编码解码_js base64-CSDN博客)
ArrayBuffer
ArrayBuffer
本身是不可变的,意味着一旦创建,其大小不能更改。- 字节单位:
ArrayBuffer
的容量是以字节为单位的,因此当你创建一个ArrayBuffer
时,需要指定它的大小(以字节为单位)。 - 访问数据:直接使用
ArrayBuffer
并不容易,通常会通过视图(views),如TypedArray
或者DataView
来读取或写入其中的数据。
创建 ArrayBuffer
可以通过构造函数创建一个新的 ArrayBuffer
:
const buffer = new ArrayBuffer(16); // 创建一个包含16个字节的缓冲区
console.log(buffer.byteLength); // 输出: 16
TypedArray 视图
为了方便地操作 ArrayBuffer
中的数据,JavaScript 提供了多种类型的 TypedArray
,每种类型对应不同的数值格式(例如整数、浮点数)和大小(例如8位、16位)。常用的 TypedArray
包括:
Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array
const buffer = new ArrayBuffer(16);
const uint8 = new Uint8Array(buffer); // 使用Uint8Array作为视图
uint8[0] = 42; // 设置第一个字节的值为42
console.log(uint8[0]); // 输出: 42
DataView 视图
除了 TypedArray
,还可以使用 DataView
对象来读取和写入 ArrayBuffer
中的数据。DataView
提供了更加灵活的方法来处理不同大小和格式的数据,允许你在同一个 ArrayBuffer
上混合使用不同的数据类型。
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
view.setUint8(0, 42); // 在偏移量为0的位置设置一个无符号8位整数
console.log(view.getUint8(0)); // 输出: 42
FileReader
读取文件并获取 ArrayBuffer
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>FileReader 读取 ArrayBuffer 示例</title>
</head>
<body><h2>请选择一个文件:</h2>
<input type="file" id="fileInput" /><pre id="output"></pre><script>document.getElementById('fileInput').addEventListener('change', function(event) {const file = event.target.files[0]; // 获取用户选择的第一个文件if (!file) {alert("请先选择一个文件!");return;}const reader = new FileReader();// 当读取完成时触发reader.onload = function(e) {const arrayBuffer = e.target.result; // result 是 ArrayBuffer 类型// 打印 ArrayBuffer 和它的长度console.log("ArrayBuffer:", arrayBuffer);console.log("字节长度:", arrayBuffer.byteLength);// 可选:将 ArrayBuffer 转换为 Uint8Array 查看前几个字节const uint8Array = new Uint8Array(arrayBuffer);const firstBytes = uint8Array.slice(0, 20); // 前20个字节document.getElementById('output').textContent ="前20个字节(十六进制):\n" +Array.prototype.map.call(firstBytes, b => ('00' + b.toString(16)).slice(-2)).join(' ');};// 开始读取文件为 ArrayBufferreader.readAsArrayBuffer(file);});
</script></body>
</html>
FileReader
是浏览器提供的用于异步读取文件内容的 API。readAsArrayBuffer(file)
方法会将整个文件读取为一个ArrayBuffer
。reader.onload
回调中,e.target.result
就是读取到的ArrayBuffer
。- 使用
Uint8Array
可以查看或操作原始二进制数据。 - 这种方式非常适合用来解析各种二进制格式,如:
- 图片文件(PNG/JPG)
- PDF 文件
- 音频/视频文件
- 自定义二进制协议的数据包等
Node.js 中的 ArrayBuffer
在 Node.js 中也有 ArrayBuffer,它允许你处理通用的、固定长度的二进制数据缓冲区。ArrayBuffer 是 JavaScript 中的一个底层接口,用于表示一段连续的内存区域,这段内存不能直接操作,通常需要通过视图(如 TypedArray 或者 DataView)来访问和操作其中的数据。
在早期版本中,Node.js 和浏览器环境对于 ArrayBuffer 的支持存在一些差异,但是随着技术的发展,现在 Node.js 已经对 ArrayBuffer 提供了很好的支持,并且可以与浏览器环境兼容使用。这意味着你可以利用 ArrayBuffer 来处理文件、网络流等场景中的二进制数据。
在 Node.js 中使用 ArrayBuffer
const buffer = new ArrayBuffer(8); // 创建一个包含8个字节的缓冲区
console.log(buffer.byteLength); // 输出: 8
使用 TypedArray 访问 ArrayBuffer
要读取或写入 ArrayBuffer 中的数据,通常需要使用 TypedArray,例如 Uint8Array。
const buffer = new ArrayBuffer(8);
const view = new Uint8Array(buffer);// 写入数据
for (let i = 0; i < view.length; i++) {view[i] = i;
}// 读取数据
for (let i = 0; i < view.length; i++) {console.log(view[i]);
}
使用 DataView 访问 ArrayBuffer
如果你需要以不同的格式读取和写入数据(比如不同大小的整数或浮点数),可以使用 DataView。
const buffer = new ArrayBuffer(16);
const dataView = new DataView(buffer);// 写入不同类型的数据
dataView.setUint8(0, 255);
dataView.setFloat32(4, Math.PI);// 读取数据
console.log(dataView.getUint8(0)); // 输出: 255
console.log(dataView.getFloat32(4)); // 输出接近: Math.PI
这些例子展示了如何在 Node.js 中创建和操作 ArrayBuffer。无论你是处理文件 I/O、网络通信还是其他涉及二进制数据的操作,ArrayBuffer 都是一个非常强大的工具。此外,由于 Node.js 对 ArrayBuffer 的良好支持,使得从浏览器端到服务器端处理二进制数据变得更加统一和方便。