本文并不介绍 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
这样的东西。
为什么以二进制存在?因为电脑读写的数据都是 电信号
!而电信号就是 0
和1
。
好在我们可以把二进制、十进制、十六进制等进行转换,所以 Buffer 的每个元素看上去是十六进制,其实内存里存的都是二进制。
Buffer 的每个元素取值范围是多少呢?
- 00 – ff(十六进制)
- 0 – 255(十进制)
- 00000000 – 11111111(二进制)
255 这个数字肯定见过不少,比如 css 中的 rgba 每个值的范围是 0-255
而 255 其实跟 ASCII 码 紧紧相连,回顾一下上面代码中打印 hello 的 buffer:<Buffer 68 65 6c 6c 6f>
,然后对照下面这个 ASCII 表
再对照 buffer 里的每个元素:
是不是一下就明白了,原来数据就是这样纸的呀。
当然,上面的 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);
});
打印结果如下:
从图看出,hello.log
数据很多,一个 buffer(公交车)装不完,打印了好几次的 chunk 才完成写入,每个 chunk 都是一个 buffer,都填满了数据 (人)。流可以看成是公交司机,流的作用就是将 buffer 从一个地方(起点) 运送的另一个地方(终点)。
总结
现在捋一下:
- Buffer 就是在内存中开辟一段空间,用来装数据的
- 数据都是二进制的,记住电信号(010101)
- Stream 的三大原则:有源头、有终点、源头流向终点。
- Stream 就像司机,它的作用就是将装着数据的 Buffer 开向终点