关于Node缓冲区的完整介绍
你做了多年的Node开发者,但却从未接触过Node缓冲区?也许,你已经遇到过几次这个术语,但总是回避学习缓冲区是什么?你可能从来没有真正需要使用过缓冲区。Node.js不是一种迫使程序员直接处理程序如何管理内存的语言。但是,如果你致力于走更多的路,成为一个专业的Node开发者,你就必须努力学习缓冲区等概念,以了解Node是如何在引擎盖下工作的。
乍一看,你会觉得Node缓冲区是一个如此复杂的话题,难以理解。但实际上,情况并非如此。当你看的所有在线教程都是从创建Node缓冲区和操作它们开始的,而没有首先解释缓冲区实际上是什么,问题就开始了。为了不在这里犯同样的错误,我将不得不先解释什么是缓冲区。但在理解什么是缓冲区之前,我们必须解决在试图理解缓冲区时出现的其他几个概念。
为了正确理解缓冲区,我们应该了解二进制数据、字符编码和流。如果你还不明白这些东西与缓冲区有什么关系,不要担心,它们最后都会一起解释缓冲区是什么。
什么是二进制数据?
如果你已经知道什么是二进制数据,你可以直接跳到下一个主题。其他人就应该坚持下去,看看什么是二进制数据。
二进制数系统是另一个像我们使用的十进制数系统一样的数系统。与十进制数制不同的是,十进制数制使用0-9的数字来表示数字,二进制数制只使用0和1的数字来表示数字。下面是一些二进制数的例子。
0, 1, 10, 101, 1011011, 1000101
二进制数中的每个数字在计算机科学中被认为是一个比特。8个比特的组合被称为一个字节。但是,计算机科学与二进制数有什么关系?计算机使用二进制数来存储和表示数据。因此,存储在计算机中的每一种数据最终都被存储为一组二进制数字。我们把这些数据称为二进制数据。
为了将每一种类型的数据存储为二进制数据,计算机应该知道如何将它们转换为二进制数据。计算机有不同的机制来实现这一点。让我们看看它们是什么。
计算机如何将数字转换为二进制数据?
将数字转换为二进制数据只是一种数学方法。你可以参考二进制数字运算和数字系统转换所涉及的数学,以了解更多这方面的信息。然而,使用这种数学方法,十进制数字9可以表示为二进制的101,其他整数也是如此。计算机有能力自行进行这种转换。
计算机如何将字符转换为二进制数据?
对这个问题的简单解释是 "每个字符都有一个与之相关的独特的二进制数字"。这个唯一的数字被称为该字符的码位或字符代码。你可以使用Javascript中的charCodeAt 函数来查找每个字符的字符代码。
'a'.charCodeAt() //outputs 97
'A'.charCodeAt() //outputs 65
有两个主要的标准,用于为每个字符分配字符代码。ASCII和Unicode。无论何种编程语言,赋予字符的字符代码都是一样的。ASCII最多使用7位来表示一个字符,而Unicode最多使用16位。这种差异使Unicode比ASCII的范围更广,可以代表更多的字符,并使Unicode成为这两种标准中最受欢迎的。
找到每个字符的字符点是计算机将字符转换为二进制数据时唯一要做的事吗?答案是:不是。要将字符转换为二进制数据,还有一个步骤需要遵循。那就是字符编码。
什么是字符编码?
我之前提到过,ASCII最多可使用7位,Unicode最多可使用16位来表示一个字符。但计算机不必总是使用Unicode的所有16位来表示一个字符。例如,字符'A'可以用最少7位来表示。如果计算机用16位来存储'A',用前导0填充二进制数字,就会浪费系统资源。
这就是字符编码的作用。字符编码标准决定了计算机应该用多少位来表示一个字符。UTF-8、UTF-16和UTF-32是字符编码标准的一些例子。
UTF-8使用8位字节的块来表示字符。它可以用1-4个字节对所有Unicode字符进行编码。现在,如果计算机使用UTF-8标准对 "A "进行编码,那么存储的二进制值是01000001,其中有一个额外的前导0。
这样就完成了将字符转换为二进制数据的过程。将字符串转换为二进制数据,无非是将每个字符转换为二进制数据。计算机使用更多的标准和方法来将图像、音频和视频数据转换为二进制数据。
现在谈到了流的概念。让我们看看它们是什么。
什么是流?
数据流是正在从一个地方移动到另一个地方的数据集合。在我们的例子中,我们谈论的是二进制数据流,它是正在从一个地方移动到另一个地方的二进制数据的集合。
一个流由大量的数据组成。但计算机不必等待流中的所有数据,就可以开始处理。当发送流到某个目的地时,流中的数据不会因为其大尺寸而被一次性发送。相反,流被分成较小的数据块。目的地收集接收块,一旦有足够的块可用,就开始处理它们。
接收数据流的目的地打算以某种方式处理数据--读取、操作或写入数据。但是,目的地的数据处理器的容量有一个最大和最小数据量的限制,它可以一次性处理。那么,当目的地收到不适合这个限制的数据块时会发生什么?目的地不能丢弃它们。然而,目的地可以使用一种机制来存储收到的数据块,直到它们被处理器接受。这就是缓冲区的作用。但首先,我们应该知道缓冲区到底是什么,以了解它们如何帮助存储数据块。
什么是缓冲区,它们有什么作用?
缓冲区是计算机内存中的一个小存储空间,通常在RAM中。在目标处理器准备好接受从流中接收的数据块之前,缓冲区作为它们的等待区。
如果目的地从流中接收数据的速度超过了它处理数据的速度,这些多余的数据就会在缓冲区中 "等待",直到处理器腾出手来接受更多的数据。如果目的地从流中接收数据的速度慢于它能处理的数据的速度,换句话说,如果此刻可用的数据块的数量低于处理器能接受的最小数据量,这些数据块就在缓冲区中 "等待",直到有足够数量的数据可用。
所以,这就是缓冲区的作用:一个等待区,让流媒体数据等待,直到数据处理器准备好接受它们。无论哪里有流媒体,你都可以看到缓冲区在引擎盖下工作,以存储尚未处理的数据块。
你可能听说过这个概念,叫做缓冲。当你在看一个YouTube视频时,有时视频一直在加载,而没有恢复视频的时间。这是因为你的浏览器正在等待更多的视频流数据块的到来。在浏览器收到足够的数据块之前,它们被储存在这些缓冲区内,等待处理器接受它们。因此,被称为 "缓冲"。这正是Node.js中二进制流的情况。
当我们试图在Node程序中读取一个大文件时,也会发生同样的事情。这里使用的缓冲区存储了通过文件流发送的数据块,直到有足够的数据再传递给程序。这个过程再次被称为缓冲。
但Node.js是如何使用缓冲区的?
现在,你明白了缓冲区的基本概念以及为什么需要它们。但你可能仍然想知道为什么Node需要缓冲区。
嗯,答案很简单。当你向网络服务器发送HTTP请求时,该请求是作为TCP流通过网络发送的,这是一个二进制数据流。所以,你建立的所有Node服务器都必须处理流和缓冲区。
当你使用fs.readFile() 方法读取一个文件时,它通过回调或承诺返回一个缓冲区对象。
简而言之,Node.js中一些最重要的模块不断处理缓冲区和缓冲区操作。你甚至可能已经和缓冲区打过交道了,尽管是在不知不觉中。作为一个Node开发者,你还需要什么理由来深入学习Node缓冲区?
Node.js中缓冲区的创建和操作
Node.js提供了一个Buffer类,可以让你轻松地创建缓冲区并对其进行操作。让我们看看我们能用它做什么。
//create a buffer
let buffer1 = Buffer.alloc(100)
这创建了一个大小为100的缓冲区,这意味着该缓冲区存储了100字节的零。
你也可以从字符串和整数数组中创建一个缓冲区。
let buffer2 = Buffer.from("I'm learning Node Buffer")
//This encodes the given string and stores it as binary data
let buffer3 = Buffer.from([1, 2, 90, 55])
//stores each integer in binary
你可以使用索引访问缓冲区中的每个字节。
buffer2[0] //returns 73 for ‘I’
buffer2.toString() //returns ‘I'm learning Node Buffer’
现在让我们来看看如何向缓冲区写入。
buffer2.write("Hi")
buffer2.toString() //returns ‘Hi’
写入方法会覆盖缓冲区中的现有内容,并将其改为你提供的值。
//change the stored value at a given index
buffer2[0] = 80
buffer2.toString() //returns ‘Pi’
//get the buffer length
buffer1.length //returns 100
buffer3.length //returns 4
总结
正如你在这篇文章中所看到的,缓冲区是Node.js在引擎盖下工作的基础。理解这些概念对于成为一个更好的Node开发者至关重要。这些知识可以帮助你编写优化的Node程序,并意识到语言的局限性以及如何绕过它们。所以,当你下次遇到与Node.js有关的令人生畏的术语时,不要犹豫,像我们与Buffers一样迎难而上。