Node.js Buffers 完整指南
2021/11/7 1:10:20
本文主要是介绍Node.js Buffers 完整指南,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
在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集」阅读不迷路
原文地址
这篇关于Node.js Buffers 完整指南的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-25Vue3学习:从入门到初步掌握
- 2024-12-25Vue3入门:新手必读的简单教程
- 2024-12-23【JS逆向百例】爱疯官网登录逆向分析
- 2024-12-21Vue3教程:新手入门到实践应用
- 2024-12-21VueRouter4教程:从入门到实践
- 2024-12-20Vue3项目实战:从入门到上手
- 2024-12-20Vue3项目实战:新手入门教程
- 2024-12-20VueRouter4项目实战:新手入门教程
- 2024-12-20如何实现JDBC和jsp的关系?-icode9专业技术文章分享
- 2024-12-20Vue项目中实现TagsView标签栏导航的简单教程