学Node必须掌握的Buffer和Stream

本文并不介绍 Buffer 和 Stream 使用的api,而是把对 Buffer 和 Stream 的理解带给大家。

之前发了篇文章《Nodejs核心模块简介》,笼统的介绍了下 Events模块、fs模块、stream的使用、http模块。

文章也在我的 github 博客上,欢迎订阅。

因为想学好 node 这些东西几乎是必须掌握的。这篇文章来说一下在 node 中几乎无处不在的 Buffer 和 Stream,什么是 Buffer 以及它和 Stream 到底什么关系? 马上揭晓。

Buffer

Buffer 是个类数组的对象,可以把它当做数组更好理解些,只不过里面存的是二进制数据。

先创建个 buffer 来看看它打印出来的样子:

const str = 'hello';
const buf = Buffer.from(str);

console.log(buf); // <Buffer 68 65 6c 6c 6f>

buf 里装的数据是字符串 hello,而 buf 的长度为 5 ,hello 的长度也是 5,所以 Buffer 中每个元素占一个字节(英文每个字母是一个字节)。

Buffer 是什么

从代码使用来看,Buffer 是类数组对象。
从内存角度看,Buffer 是在内存中开辟的一块区域。

Buffer 翻译过来是缓冲器,它主要用来暂存数据。

为了更好理解,用大白话把上面哪句翻译一下:Buffer 就是我们常坐的公交车就是数据,人上车就表示在 Buffer 中输入数据, 到站了人就下车,Buffer 里的数据就会输出

比如我们填写完表单,发送 http 请求到服务端,我们的数据就会暂存在 Buffer 中,服务端取的数据就是从暂存的 Buffer 里取的

Buffer 里装的是什么

废话!装的当然是数据了!没错 是数据…

<Buffer 68 65 6c 6c 6f>, 从刚才打印结果看,Buffer 显示的每个元素都是十六进制,但这只是为了方面查看,在控制台显示时是十六进制而已。。。

这里问问大家,数据在内存中是什么? 没错 是二进制,就是类似010101这样的东西。
为什么以二进制存在?因为电脑读写的数据都是电信号! 而电信号就是 01

好在我们可以把二进制、十进制、十六进制等进行转换,所以 Buffer 的每个元素看上去是十六进制,其实内存里存的都是二进制。

Buffer 的每个元素取值范围是多少呢?

  • 00 – ff(十六进制)
  • 0 – 255(十进制)
  • 00000000 – 11111111 (二进制)

255 这个数字肯定见过不少,比如 css 中的 rgba 每个值的范围是 0-255

而 255 其实跟 ASCII码 紧紧相连,回顾一下上面代码中打印 hello 的 buffer :<Buffer 68 65 6c 6c 6f>,然后对照下面这个 ASCII 表

《学Node必须掌握的Buffer和Stream》

再对照 buffer 里的每个元素:
《学Node必须掌握的Buffer和Stream》

是不是一下就明白了, 原来数据就是这样纸的呀。
当然,上面的 hello 使用的是国际统一码,是 0 - 127,后128个(128—255)称为扩展ASCII码,目前许多基于x86的系统都支持使用扩展(或“高”)ASCII。

Stream 与 Buffer

亲! 先把进制问题和ASCII码放一边,现在你的脑子里只有公交车

Stream 翻译过来就是流,流动的意思,《Nodejs核心模块简介》里也简单的介绍了这块内容,有兴趣可以看看。

既然 Stream 是流动的,那它跟 Buffer 到底有啥联系?

现在回到 人和公交车 的问题,上面说 是数据,公交车本身是 Buffer,Buffer 里有没有数据 取决于在不在里面。

注意,我上面说的是公交车本身,没有说公交车有没有在跑。

所以,聪明的你猜到了,跑着的公交车就是 Stream。

流的原则是:有源头、有终点、源头流向终点。
公交车就是这样,从起点发车,载着数据(人)往终点跑。

光说不行,来看一段代码:

const fileReadStream = fs.createReadStream('./logs/hello.log');
const fileWriteStream = fs.createWriteStream('./logs/hello2.log');

fileReadStream.on('data', chunk => {
  console.log(chunk);
  fileWriteStream.write(chunk); 
});

打印结果如下:
《学Node必须掌握的Buffer和Stream》

从图看出,hello.log数据很多,一个 buffer(公交车) 装不完, 打印了好几次的 chunk 才完成写入,每个 chunk 都是一个buffer,都填满了数据(人)。 流可以看成是公交司机,流的作用就是将 buffer 从一个地方(起点)运送的另一个地方(终点)。

总结

现在捋一下:

  1. Buffer 就是在内存中开辟一段空间,用来装数据的
  2. 数据都是二进制的,记住电信号(010101)
  3. Stream 的三大原则:有源头、有终点、源头流向终点。
  4. Stream 就像司机,它的作用就是将装着数据的 Buffer 开向终点
    原文作者:alwaysVe
    原文地址: https://segmentfault.com/a/1190000020129087
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞