首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Node Buffers 完整指南

身为Node开发人员这些年来,你是否从未遇到过Node缓冲区(Buffer)这个概念呢?也许这个术语你见过几次,但每次都不想一探究竟?你可能的确没遇到过要使用缓冲区的场景,毕竟Node.js并不是那种要求程序员直接和程序管理内存的操作打交道的语言。但是,如果你想要成为专业Node开发人员,愿意为此付出更多的努力,那么你就必须深入探索缓冲区之类的概念,从而理解Node的底层工作机制。

本文最初发布于livecodestram.dev网站,经网站授权由InfoQ中文站翻译并分享。

初看上去,你会觉得Node缓冲区是一个很难理解的主题,但事实并非如此。问题在于你看过的所有在线教程上来就会创建一些Node缓冲区,然后开始操作它们,却没有提前解释到底这是什么东西。为了避免在这篇文章中犯同样的错误,我会首先解释什么是缓冲区。但在此之前,我们必须搞明白伴随缓冲区出现的其他一些概念。

为了正确理解缓冲区,我们应该了解二进制数据、字符编码(character encoding)和流(stream)。你可能还不明白它们和缓冲区有什么关系,先别急,搞懂它们后就能知道缓冲区是什么意思了。

什么是二进制数据?

如果你已经知道了什么是二进制数据,则可以直接跳到下一个主题。否则就请读下去,了解什么是二进制数据。

二进制数字系统是类似我们常用的十进制的另一个数字系统。十进制使用0-9的数表示数字,而二进制仅使用0和1表示数字。下面是二进制数的一些示例。

代码语言:javascript
复制
0, 1, 10, 101, 1011011, 1000101

在计算机科学中,二进制数中的每个数字均被视为一个。8个位合称一个字节。那么计算机科学与二进制有什么关系?计算机使用二进制数字来存储和表示数据。因此,存储在计算机中的每种数据最终都将存储为一组二进制数。我们称这些数据为二进制数据。 为了将所有类型的数据都存储为二进制数据,计算机应该知道如何将它们转换为二进制数。计算机为实现这一目的有很多种机制,下面具体介绍。

计算机如何将数字转换为二进制数据?

将数字转换为二进制数据只是一种数学处理。十进制数字9可以用二进制表示为101,其他整数也有自己的对应。计算机具备自行做这种转换的能力。

计算机如何将字符转换为二进制数据?

对这个问题的简单解释是“每个字符都有一个与之关联的唯一二进制数”。这种唯一编号称为字符的代码点字符码。你可以在Javascript中使用charCodeAt函数来查找每个字符的字符码。

代码语言:javascript
复制
'a'.charCodeAt() //outputs 97
'A'.charCodeAt() //outputs 65

有两大标准用来为每个字符分配字符码:ASCII和Unicode。无论使用哪种编程语言,它们各自赋予字符的字符码都是一样的。ASCII最多使用7位来表示字符,而Unicode最多使用16位。所以Unicode提供了比ASCII更大的范围,可以表示更多的字符,进而成为了最受欢迎的标准。 计算机将字符转换为二进制数据时,需要做的唯一工作就是查找每个字符的字符点吗?答案是否定的。你还需要执行一个将字符转换为二进制数据的步骤。那就是字符编码。

什么是字符编码?

我之前提到过ASCII最多可以使用7位,而Unicode最多可以使用16位来表示字符。但是计算机用不着一直使用Unicode的全部16位来表示字符。例如,字符“A”可以使用至少7位来表示。如果计算机用前导0填充二进制数,使用全部16位来存储“A”,就是在浪费系统资源。

这里就轮到字符编码登场了。字符编码标准决定了计算机用来表示字符的位数。UTF-8、UTF-16和UTF-32就是其中一些字符编码标准。

UTF-8使用8位(一字节)的块表示字符。它可以使用1-4个字节对所有Unicode字符进行编码。现在,如果计算机使用UTF-8标准对“A”进行编码,则存储的二进制值为01000001,带一个前导0。

这样就完成了将字符转换为二进制数据的过程。将字符串转换为二进制数据时,无非就是将每个字符都转换为二进制数据。计算机将图像、音频和视频数据转换为二进制数据时会用到更多的标准和方法。

现在出现了的概念。我们来看看它又是什么。

什么是流?

流是从一处移到另一处的数据的集合。这里我们谈论的是二进制数据流,它是从一个地方移动到另一个地方的二进制数据的集合。

一条流中会包含大量数据。但是计算机不必等待流中的所有数据到位也可以开始处理它们。将流发送到某个目的地时,由于数据太多了,因此不会一次发送完流中的全部数据,而是将流分为许多较小的数据块。目标会接收这些块并归拢起来,并在有足够的块可用时开始处理它们。

接收流的目标会以某种方式处理数据——可以是读取、操作或写入数据。但是目标处的数据处理器的能力,限制了它一次可以处理的数据量的上下限。那么,当目标接收到不符合此限制的数据块时会发生什么呢?目标无法丢弃它们。然而,目标可以使用一种机制来存储接收到的块,直到它们可以被处理器处理为止。这里就引入了缓冲区的概念。但首先我们应该知道缓冲区到底是什么,才能进一步理解它们如何帮助存储数据块。

什么是缓冲区,它们要做什么?

一个缓冲区是计算机内存(通常是RAM)中一处较小的存储空间。在目标处理器准备好处理来自流的数据块之前,缓冲区充当后者的等待区域。

如果目标从流中接收数据的速度快于其处理数据的速度,则这些多余的数据将在缓冲区中“等待”,直到处理器可以处理新的数据为止。如果目标从流中接收数据的速度慢于其处理数据的速度,换句话说,如果当前可用的块数量低于处理器可接受的最小数据量,则这些数据块将在一个缓冲区中“等待”,直到有足够数量的数据可用为止。

所以缓冲区指的就是一处等待区域,流数据在这里等待处理器,直到后者准备好处理数据为止。只要是有流存在的地方,你都会看到后台存在缓冲区来存储尚未处理的数据块。

你可能已经听说过缓冲(buffering)这个概念。当你观看YouTube视频时,有时视频会加载一段时间,然后才会继续播放。这是因为你的浏览器正在等待视频流的更多数据块就位。在浏览器收到足够的数据块之前,它们会存储在这些缓冲区中,并等待处理器处理。这就是“缓冲”这个名词的来历。这也正是Node.js中二进制流会遇到的情况。

当我们尝试在Node程序中读取大文件时,也会发生同样的事情。这里使用的缓冲区会存储通过文件流发送的数据块,直到有足够的数据可用,然后再将其传递给程序。此过程也称为缓冲。

但是Node.js如何使用缓冲区?

现在,你已经了解了缓冲区的基本概念以及为什么需要它们。但是你可能还想知道Node为什么需要缓冲区。

答案很简单。当你将HTTP请求发送到Web服务器时,该请求会作为TCP流通过网络发送,这是一个二进制数据流。因此,你构建的所有Node服务器都必须处理流和缓冲区。

当你使用fs.readFile()方法读取文件时,它将通过回调或promise返回一个缓冲区对象。

简而言之,Node.js中一些最重要的模块会不断处理缓冲区和缓冲区操作。你可能已经在不知不觉中用过了缓冲区。

Node.js中的缓冲区创建和操作

Node.js提供了一个Buffer类,可让你轻松创建和操作缓冲区。我们来看看用它能做什么。

代码语言:javascript
复制
//创建一个buffer
let buffer1 = Buffer.alloc(100)

这将创建一个大小为100的缓冲区,这意味着该缓冲区会存储100个字节的零。 你还可以从字符串和整数数组创建缓冲区。

代码语言:javascript
复制
let buffer2 = Buffer.from("I'm learning Node Buffer")
//编码给定字符串并将其存储为二进制数据
let buffer3 = Buffer.from([1, 2, 90, 55])
//将每个整数存储为缓冲区

你可以使用索引访问缓冲区中的每个字节。

代码语言:javascript
复制
buffer2[0] //returns 73 for ‘I’
buffer2.toString() //returns ‘I'm learning Node Buffer’

现在我们来看看如何写入缓冲区。

代码语言:javascript
复制
buffer2.write("Hi")
buffer2.toString() //returns ‘Hi’

write方法将覆盖缓冲区中的现有内容,并将其更改为你提供的值。

代码语言:javascript
复制
//使用指定的索引更改存储的值
buffer2[0] = 80 
buffer2.toString() //returns ‘Pi’
//获取缓冲区长度
buffer1.length //returns 100
buffer3.length //returns 4

你可以查看Node.js文档(https://nodejs.org/api/buffer.html),了解还可以使用缓冲区做些什么事情。

小结

如你在本文中所见,缓冲区对于Node.js的工作机制而言至关重要。了解这些概念可以帮助你成为更优秀的Node开发人员。这些知识可帮助你编写优化的Node程序,并了解这种语言的局限性,知道如何解决它们。因此,下次你遇到与Node.js相关的令人生畏的术语时,请不要犹豫,应该像对待缓冲区一样直接面对它。

原文链接:https://livecodestream.dev/post/2020-06-06-a-complete-introduction-to-node-buffers

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/a1XgEh2UhMsVu0HqJVJv
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com