完全理解Node.js中的Buffer

每当在Node.js中遇到Buffer,Streambinary data之类的单词时,是否老是像我同样感到困惑? 认为它们并非经常使用的,而只适合Node.js专家和包开发人员去使用。html

实际上,这些单词是很是重要的,尤为对于用Node.js进行web开发而没有任何CS学位的人员。node

固然,若是你选择继续作一个普通的Node.js开发人员,你可能永远不会直接使用它们。可是若是你想对Node.js的理解提高到下一个级别,那么你确实须要更深刻地了解Node的许多核心特性。好比Buffer。这正是我写这篇文章的目的——帮助咱们揭开其中一些特性的神秘面纱,并将Node.js的学习带到下一个层次。git

在开始前,先看一下Node.js官方文档对Buffer的说明github

… mechanism for reading or manipulating streams of binary data. The Buffer class was introduced as part of the Node.js API to make it possible to interact with octet streams in the context of things like TCP streams and file system operations.web

让咱们用简单易懂的语言来从新描述它:api

Buffer类做为Node.js API的一部分引入,使操做二进制数据流或与之交互成为可能。
复制代码

接下来咱们更深刻的去了解Buffer,streams,binary data。浏览器

什么是二进制数据

你可能已经知道计算机以二进制文件存储和表示数据。二进制就是1和0的集合。例如,下面是5个不一样的二进制文件,5组不一样的1和0:并发

10, 01, 001, 1110, 00101011
复制代码

二进制中每一个1和0都称为Bit,这是二进制数字的一种简短形式。ide

为了存储或表示一段数据,计算机须要将该数据转换为二进制表示。例如,要存储数字12,计算机须要将12转换成二进制表示,即1100。学习

可是在工做中,number并非惟一的数据类型。一般上还会有string,images,videos。计算机知道如何用二进制表示全部的数据类型。好比计算机如何用二进制表示string类型的“L”呢?要将任何字符存储在二进制文件中,计算机首先将该字符转换为数字,而后将该数字转换为二进制表示形式。对于字符串“L”,计算机首先将L转换成表示L的数字。

打开浏览器控制台,输入“L”. charcodeat(0)。这时控制台会显示出数字76,这是字符“L”的数字表示。可是计算机又是如何知道每一个字符表示的确切数字呢?它怎么知道用76来表示L?

字符集

字符集已经定义好的表示每一个字符的确切数字的规则。咱们对这些规则有不一样的定义,最流行的包括Unicode和ASCII。JavaScript能够很好地处理Unicode字符集。因此,浏览器中的Unicode规定76应该表示L

咱们已经看到计算机是如何用数字表示字符的。转换成数字以后计算机再把76转换它的二进制表示。

字符编码

正若有一些字符集规则定义数字应该怎么样表示字符同样,也有一些规则定义了数字应该如何在二进制文件中表示。具体来讲,就是用多少位来表示数字。这叫作字符编码。

字符编码的一个规则是UTF-8。UTF-8声明字符应该以bytes编码。一个byte是8位(bit)的集合 —— 8个1和0。所以,UTF-8规定应该使用8个1和0来表示二进制中任何字符。

以前的例子提到,数字12用二进制表示为 1100,可是用UTF-8表示应该是8位才对。因此UTF-8规定,计算机须要在不满8位的二进制数字左边添加更多的位,以使其成为一个字节。因此12应该存储为00001100

所以 76 在UTF-8规则下存储表示为:01001100

这就是计算机在二进制文件中存储字符串或字符的方式。一样,计算机也规定了图片和视频应该如何转换、编码和存储在二进制文件中的规则。计算机将全部数据类型存储在二进制文件中。

如今咱们了解了什么是二进制数据,接下来咱们介绍一下什么是二进制数据流。

js中的Stream只是表示随着时间的推移从一个点移动到另外一个点的数据序列。整个概念是,你有大量的数据要处理,可是你不须要等到全部的数据均可用后才开始处理它。基本上,这个大数据被分解并以块的形式发送。所以,从Buffer的原始定义来看,这仅仅意味着二进制数据正在文件系统中移动。例如,将存储在file1.txt中的文本移动到file2.txt。

可是Buffer究竟如何帮助咱们在流与二进制数据进行交互或操做呢?Buffer究竟是什么?

Buffer

咱们已经提到,数据流是数据从一个点移动到另外一个点,可是它们到底是如何移动的呢?

一般数据的移动是为了处理或读取数据,并根据数据作出决策。在这个过程当中,可能须要数据到达一个最小量或者最大量才能进行处理。所以,若是数据到达的速度快于进程消耗数据的速度,那么多余的数据须要在某个地方的等待来处理。另外一方面,若是进程消耗数据的速度快于数据到达的速度,那么早到达的少数数据须要等待必定数量的数据到达,而后再发送出去进行处理。

那个“等候区”就是Buffer!它是计算机中的一个小物理位置,一般位于RAM中,数据在RAM中被临时收集、等待,并最终发在流过程当中送出去进行处理。

咱们能够把整个stream和buffer过程看作一个汽车站。在某个汽车站,汽车直到有必定数量的乘客或者是一个特殊的时间才能够发车。此外,乘客可能在不一样的时间以不一样的速度到达。不管是旅客仍是汽车站都不能控制旅客到达车站的时间。提早到达的乘客须要等汽车发车。当有些乘客到达时,乘客已经满员或者汽车已经离开,须要等待下一辆汽车。

不管什么状况,总有一个等待的地方。这就是Node.js的Buffer! js不能控制数据到达的速度或时间,也不能控制流的速度。它只能决定什么时候发送数据。若是尚未到时间,Node.js将把它们放在buffer中,即RAM中的一个小位置,直到将它们发送出去进行处理为止。

一个典型的例子是,当你在观看流媒体视频时,能够看到buffer在工做。若是你的互联网链接足够快,流的速度将足够快,能够当即填满Buffer并发送出去进行处理,而后再填入另外一个Buffer,而后发送出去,再发送一个,再发送一个,直到流完成为止。

可是若是你的链接很慢,在处理了第一组到达的数据后,视频会被卡主,这意味着程序正在收集更多的数据,或者等待更多的数据到达。当buffer被填满并处理后,播放器会继续播放视频。在播放的同时,更多的数据将继续到达并在buffer中等待。

与Buffer交互

Node.js在处理流期间会自动建立buffer,咱们也能够经过Nodejs提供的API本身建立buffer。根据你的需求,这里有几种不一样的方法能够建立buffer。

// Create an empty buffer of size 10.
// A buffer that only can accommodate 10 bytes
const buf1 = Buffer.alloc(10)

// Create a buffer with content
const buf2 = Buffer.from("hello buffer")
复制代码

当建立成功buffer后,你就能够开始和它进行交互了。

// 查看buffer的结构
buf1.toJSON()
// { type: 'Buffer', data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }

buf2.toJSON()
//{ type: 'Buffer',data: [ 104, 101, 108, 108, 111, 32, 98, 117, 102, 102, 101, 114 ]}

buf1.length // 10
buf2.length // 12

// 写操做
buf1.write("Buffer really rocks!")

// decode
buf1.toString() // 'Buffer rea'
// 由于buf1建立时只分配了10byte的空间。超过的将不会被存储。
复制代码

更多的交互API,能够查看官方文档

但愿这篇介绍能帮助您更好地理解Node.js Buffer。

更多有关js的文章,请关注github

相关文章
相关标签/搜索