ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Node.js Buffers 完整指南

2021-11-06 23:58:39  阅读:226  来源: 互联网

标签:Node const 字节 Buffer js buffer 缓冲区 Buffers buff


在Node.js中,buffers 是一个可以存储二进制数据的特殊类型。buffer 代表内存块-通常指在计算机中分配的 RAW 。buffer 的大小是不能更改的。

buffer 存储字节。八位(Bits)序列称为一个字节(byte)。位(Bits)在计算机中是最基本的存储单元,他们可以保存0 或 1的数值。

译者注:计算机是存储二进制数据的,二进制主要是 0 和 1的集合。

Node.js 在全局作用域中可直接使用 Buffer 类(不需要像其他模块一样导入)。使用这个API,你可以获取一系列函数和抽象来操作原始的二进制文件。

一个 buffer 在Node.js中就如以下表示:

<Buffer 61 2e 71 3b 65 2e 31 2f 61 2e> 

在示例中,你可以看到 10对字母和数字的组成,每一对表示存储在缓冲区中的字节,这个缓冲区的总大小为10。

你可能会问自己:“如果这些是位和字节,那 0 和 1 在哪里呢?”

那是因为Node.js使用十六进制系统显示字节。这样,每个字节都可以仅使用两位数表示(一对数字和字母是从0-9 和 “a” to “f”)

为什么需要 buffers?因为在 buffers 出现之前,在JavaScript中并没有简单的方式去处理二进制数据,你必须采用类似于字符串的primitives,这种方式是比较慢的,也没有专门的工具来处理二进制文件。所以Buffers 会被创建,且提供一些简单和高效的API可以操作位和字节。

buffers使用

让我们看看使用buffers可以做的一些事情。

你会注意到使用 buffer 有点类似于 JavaScript 中使用数组的方式。例如,你可以使用.slice(),concat().length 操作buffer。 缓冲区也是可迭代的,可以使用例如for-of之类的构造器迭代。

如果你是在计算机上操作示例,记住 Buffer 类是全局的。你不需要单独的引入。

译者注: 虽然 Buffer 类在全局作用域内可用,但仍然建议通过 import 或 require 语句显式地引用它

创建 buffers

有三种方法创建Buffers。

  • Buffer.from()
  • Buffer.alloc()
  • Buffer.allocUnsafe()

buffers在以前是使用 Buffer 类构造函数(例如,new Buffer() )创建的。此语法已被弃用。

Buffer.from()

使用buffer.from()是创建buffer 的最直接方法。它可接受字符串、数组、ArrayBuffer,或也可以是另一个 buffer 实例。根据传递的参数, Buffer.from() 将以不同的方式创建缓冲区。

传入字符串时,将创建一个包含该字符串的新缓冲区对象。默认情况下,它将使用 utf-8 作为编码解析你的输入(点击here查看支持的所有编码类型)

// 使用字符串"heya!"创建一个新缓冲区
// 如果第二个参数,没有传入编码类型,将使用默认 'utf-8' 编码类型
Buffer.from("heya!");

// 创建一个和上面相同的缓冲区,但是输入十六进制编码字符串
Buffer.from("6865796121", "hex");

你还可以将字节数组传给Buffer.from()。这里,我传入跟之前相同的字符串(“heya!”),但是使用十六进制的字符数组表示。

// Also writes 'heya!' to the buffer, but passes a array of bytes
Buffer.from([0x68, 0x65, 0x79, 0x61, 0x21]);

如果你不熟悉0xNN语法,则意味着 0x之后的字符应该解释为十六进制值。

将buffer实例传入 Buffer.from()时,Node.js 会复制该实例到当前的缓冲区中。由于新缓冲区会分配在不同的内存区域中,故你可以独立的修改它。

const buffer1 = Buffer.from('cars');
const buffer2 = Buffer.from(buffer1);

buffer2[0] = 0x6d;
console.log(buffer1.toString()); // --> "cars"
console.log(buffer2.toString()); // --> "mars"

这些应该覆盖了你使用 Buffer.from() 的大多数情况。详情可参考文档 docs

Buffer.alloc()

.alloc() 方法在您想要创建空缓冲区时很有用,不需要初始化数据填充。默认情况下,它接受一个数字并返回一个给定大小并且填充了 0 的缓冲区。

Buffer.alloc(6) // --> <Buffer 00 00 00 00 00 00>

你可以在之后填充你想要的任何数据。

const buff = Buffer.alloc(1);

buff[0] = 0x78;

console.log(buff.toString('utf-8')); // x

你还可以使用 0 以外的其他内容和给定的编码填充缓冲区。

Buffer.alloc(6, "X", "utf-8");

Buffer.allocUnsafe()

使用 .allocUnsafe(),可以跳过清理和用 0 填充 buffer 的过程。 buffer 将被分配在可能包含旧数据的内存区域中(这就是“Unsafe”的部分来源)。例如,以下代码很可能每次运行时都会打印一些随机数据

// 分配大小为 10000 的随机内存区域
// 不清理它(用 0 填充)所以它可能包含旧数据
const buff = Buffer.allocUnsafe(1000);

// 打印加载的随机数
console.log(buff.toString('utf-8'));

.allocUnsafe() 有一个好处的使用情况是当你复制一个被安全分配的缓冲区。由于你复制buffer 时是会完整的覆盖,所以所有旧字节数据都将被可预测的数据替换:

// Creates a buffer from a string
const buff = Buffer.from('hi, I am a safely allocated buffer');

// Creates a new empty buffer with `allocUnsafe` of the sameconst buffCopy = Buffer.allocUnsafe(buff2.length);
// length as the previous buffer. It will be initally filled with old data.
const buffCopy = Buffer.allocUnsafe(buff.length);

// Copies the original buffer into the new, unsafe buffer.
// Old data will be overwritten with the bytes
// from 'hi, I am a safely allocated buffer' string.
buff.copy(buffCopy);

console.log(buffCopy.toString());
// --> 'hi, I am a safely allocated buffer'

通常来说,.allocUnsafe()应当仅被使用在你有很好的理由使用的情况下(例如,性能优化)使用。每当使用它时,请确保永远不在没有使用新数据填充完整它的情况下返回 buffer 实例,否则你可能会泄漏敏感的信息。

写入buffers

Buffer.write()是将数据写入 buffers 的方法。 默认情况下,它将写入一个以 utf-8编码的、没有偏移(从 buffer 的第一个位置开始写入)的字符串。它会返回一个数字,是写入buffer中的字节数。

const buff = Buffer.alloc(9);

buff.write("hey there"); // 返回 9(写入的字节数)

// 如果写入的字节数超过缓冲区支持的字节数,
// 您的数据将被截断以适合缓冲区。
buff.write("hey christopher"); // retuns 9 (number of bytes written)

console.log(buff.toString());
// -> 'hey chris'

请记住,并非所有字符都会占用 buffer 中的单个字节 !

const buff = Buffer.alloc(2);

// 版权符号('©')占用两个字节,
//所以下面的操作将完全填满缓冲区
buff.write("©"); // returns 2

//如果缓冲区太小,无法存储字符,则不会写入。
const tinyBuff = Buffer.alloc(1);

tinyBuff.write("©"); // returns 0 (nothing was written)

console.log(tinyBuff);
// --> <Buffer 00> (empty buffer)

另外请注意到,2不是字符拥有最大的字节数。例如,utf-8编码类型支持最多4字节的字符。 由于无法修改缓冲区的大小,所以始终需要注意你正在编写的内容它将会占用多少空间(缓冲区的大小与内容的大小)。

另一个写入buffer的方法是通过类似于数组的语法 add方法,把字节添加到buffer的特殊位置。需要注意的是,任何超过 1 个字节的数据都需要分解并设置在buffer的每个位置

const buff = Buffer.alloc(5);

buff[0] = 0x68; // 0x68 is the letter "h"
buff[1] = 0x65; // 0x65 is the letter "e"
buff[2] = 0x6c; // 0x6c is the letter "l"
buff[3] = 0x6c; // 0x6c is the letter "l"
buff[4] = 0x6f; // 0x6f is the letter "o"

console.log(buff.toString());
// --> 'hello'

// ⚠️ 警告: 如果你尝试设置超过 2 个字节的字符到一个位置,它会失败
buff[0] = 0xc2a9; // 0xc2a9 is the symbol '©'

console.log(buff.toString());
// --> '�ello'

// 但是如果你分别写每个字节...
buff[0] = 0xc2;
buff[1] = 0xa9;

console.log(buff.toString());
// --> '©llo'

虽然你可以使用类似数组的语法写入buffers,但我建议你尽可能坚持使用 Buffer.from() 。管理输入的长度是一项艰巨的任务,并且会给你的代码带来复杂性。使用 .from(),您可以无担忧的在 buffer 中写入内容,并通过检查是否未写入任何内容(返回 0 时)来处理输入过大的情况。

迭代buffers

你可以使用类似于数组的现代JavaScript 结构去迭代 buffer。例如: 使用 for-of

const buff = Buffer.from('hello!');

for (const b of buff) {
   // `.toString(16)`返回十六进制格式内容
  console.log(b.toString(16));
}

其他的遍历方法 例如 .entries(), .values().keys()也同样也适用于 buffers,栗子:使用 .entries()

const buff = Buffer.from("hello!");
const copyBuff = Buffer.alloc(buff.length);

for (const [index, b] of buff.entries()) {
  copyBuff[index] = b;
}

console.log(copyBuff.toString());
// -> 'hello!'

走的更远: Buffers and TypeArrays

在 JavaScript(我的意思是一般的 JavaScript,不限于 Node.js)中,可以使用特殊的 ArrayBuffer 类分配内存。我们很少直接操作 ArrayBuffer 对象。相反,我们使用一组引用底层数组缓冲区的“视图”对象。这些视图对象是:

Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array等。

完整列表 请点击here

这些上面列出的视图对象统称为TypedArray。所有视图对象都通过原型从 TypedArray 继承方法。 TypedArray 构造函数不是全局公开的,必须始终使用其中一种视图方法。如果你看到一些使用 new TypedArray() 的教程或文档,这意味着它正在使用任何视图对象(Uint8Array、Float64Array 等)

在 Node.js 中,从 Buffer 类创建的对象也是 Uint8Array 的实例。它们之间有一些小的差异。你可以在此阅读 here

总结

作为初学者,buffers 是 Node.js 中的一个主题,让我感到非常困惑(另一个是流,但它值得拥有自己的帖子)。希望我能够揭开有关缓冲区的一些概念的神秘面纱,并概述 Buffer API。

我是废材壶,前端开发者,欢迎微信搜一搜「 CodeLife集」阅读不迷路

weix.png

原文地址

标签:Node,const,字节,Buffer,js,buffer,缓冲区,Buffers,buff
来源: https://blog.csdn.net/weixin_40494579/article/details/121186641

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有