美文网首页
想要更加了解node.js中的Buffer吗?来看看这个

想要更加了解node.js中的Buffer吗?来看看这个

作者: ITgecko | 来源:发表于2018-08-18 11:03 被阅读0次

    前言


    • 你是否在碰到node.js中的Buffer、流、二进制数据等词汇时感到困惑呢?是否这种困惑让你不想去理解他们,认为这些概念与你关系不大,只有node.js专家或者npm包的开发者才应该要去理解?
    • 确实这些词汇听起来可能有点吓人,特别是对于非计算机专业科班出身的人来说。
    • 遗憾的是很多node.js的教程和书籍不会让你去理解node的底层原理和为什么他们存在,而是直接教你如何使用node.js去开发web应用。甚至有的还会直接恬不知耻地告诉你不用理解原理,因为你可能不会直接地去使用他们。
    • 不过确实,作为一个普通的node.js开发者或许不需要去理解这些。
    • 但如果你感到困惑的同时也产生了好奇心,并且想竭尽全力地去满足好奇心,并且想要把自己对node的理解提升一个等级。那么真的应该深入地去理解node的核心功能,比如Buffer
    • 当介绍Buffer的时候,node的官方文档是如下介绍的:
      • Buffer是用来读取或操作二进制数据的一种机制,Buffer 类被引入作为 Node.js API 的一部分,使其可以在 TCP 流或文件系统操作等场景中处理二进制数据流。
    • emmmm,上述句子中提出了一堆专业名词,你只有拥有一定的知识基础后可能才能理解。Buffer、流、二进制数据这些词汇可能还是有点难以理解,接下来会一个一个地处理它们。

    什么是二进制数据

    • 你或许应该知道计算机底层对数据的存储和呈现都是以二进制的形式。二进制其实就是由许许多多的0和1组成的集合体。举个例子,下面就是五个不同类型的二进制数据,五个不同的01集合体。
      10, 01, 001, 1110, 00101011
    • 每个01都叫做一个比特(Bit),也是二进制位(Binary digIT)的简称。
    • 为了存储或展示一段数据,计算机需要把数据转化成二进制的表达式。举个例子,为了存储数字12,计算机会把12转换成1100的二进制形式。
    • 计算机是如何知晓该怎么做这个转化呢?好吧,这个是纯数学问题。它是我们在基础数学中学到的二进制数字系统----在base-2数字系统中表示一个数字。这是计算机能够理解的数学。
    • 但是我们平时打交道的数据类型并不只有数字类型的,还有字符串、图片、甚至视频。计算机知道如何把这些数据类型以二进制的形式来展示。让我们以字符串作为例子,计算机是如何以二进制展示一个字符串"L"呢?要以二进制的形式存储字符的话,计算机会首先把字符转换成数字,然后再把数字转换成二进制形式。所以对于字符串"L",计算机首先会把它转换成一个表示字符串"L"的数字,下面来看是如何做到的。
    • 打开你的浏览器,在console里输入以下代码:"L".charCodeAt(0)。你会看到什么?数字76?没错,这就是字符串L的数字表达式,或者说是字符编码(Character Code)或代码点(Code Point)。但是计算机是如何知道哪个数字是对应的哪个字符呢?他怎么知道76就是对应的L?

    字符集(Character Sets)

    • 字符集定义好了字符与数字的对应规则,这里有不同的对应规则。最有名的比如UnicodeASCII。JavaScript使用的Unicode字符集,其实在浏览器中就是Unicode字符集来声明的数字76应该表示L。
    • 我们已经知道计算机如何使用数字来表示字符串了,接下来计算机会把数字76转换成二进制。

    字符编码(Character Encoding)

    • 正如这里有规定字符如何与数字映射的规则,自然也会有规定数字如何与二进制映射的规则。需要明确地规定好,需要多少个比特(bits)来表示数字,这就是字符编码
    • 字符编码中有一个定义就是UTF-8,utf-8声明字符应该以字节(bytes)为单位进行编译,一字节(bytes)由一组八个比特(bits)组成,也就是8个0或者1。所以八个0或1组成的字节,可以用来表示二进制里面的任意字符。
    • 我们上面提到了,数字12的二进制表达式为1100。当在使用UTF-8声明时,数字12应该由8位组成,所以UTF-8会让计算机在1100的左边再补上4位,凑成8位组成一个字节。所以12就应该以00001100存储。这样合理吧?
    • 同样的,数字76应该存储为01001100
    • 以上就是计算机如何以二进制形式存储字符或字符串的原理。同样的计算机也有指定图片和视频如何转换成二进制形式规则,这里关键点就在于,计算机将各种类型的数据都以二进制形式存储,这就叫做二进制数据。
    • 如果你对字符编码的原理细节感兴趣的话,可以参考这个详细的文档
    • 现在我们对二进制的数据有初步理解了,但是二进制的流以及我们介绍的Buffer是如何联系起来的呢?

    流(stream)

    • 在node.js中流(stream)的简单含义就是一串数据持续地从一个地方传输到另一个地方。整体概念就是,你有一大堆数据需要传输,然后在你接收端处理数据时,不需要等待全部的数据都传输完毕。
    • 主要是大的数据会被拆分成小块的形式来进行传输和发送。目前,Buffer的原始定义就是在文件系统里处理二进制的数据流,也就是简单的在文件系统场景下,进行二进制数据的传输。就比如,把file1.txt里的文本传输到file2.txt里。

    Buffer

    • 我们已经知道流数据就是一组运动中的数据(the movement of data),在一个点传输到另一个点时产生的。通常,这些运动中的数据都是要对他们进行处理、或读取、或基于他们做一些决定的。传输过程中,程序接收数据时有一个最大值和最小值的限制。所以如果数据到达的量比程序接收消化数据的量更大,那么额外的数据就得在某处等待,直到轮到自己被处理。
    • 同样的,如果数据到达的量比程序消化的量更少,那么先到达的少量数据就得等待直到有一定量级的数据之后,再一并发送出去给程序处理。
    • 那个数据等待的区域就是buffer啦!它是计算机里的一个小的物理存储空间,通常是在RAM(随机存取存储器),在这里可以让数据临时性地聚集、等待,最后发送出去到流数据里处理
    • 我们可以把整个流和buffer看做是一个公交站台。在一些站台,一班公交车可能要等到特定的时间或者有一定数量的乘客之后,才能发车,然后乘客到达站台的速度和时间也是各自不同的。
    • 无论如何,提前到达车站的乘客,总是要等待,直到站台的公交车以他自己的规则发车。而后面到达的乘客,在当前班次已经坐满了,或者已经出发了的情况下,就只好等待下一班公交了。
    • 不管什么情况下,总要提供一个给乘客等待的地方对吧?没错,这就是node.js中的Buffer!Node.js无法控制数据到达的时间、以及传输的速度,它只能控制在正确的时间发送数据。在时候未到时,Node.js会把数据存放到buffer中——一个位于RAM中的"等待/缓冲区",直到正确的时间再把它们发送出去进行处理。
    • 一个典型的buffer缓冲区示例就是在你观看在线视频时。如果你网速足够快的话,流的传输速度也会很快,buffer可以立即被填满,然后发送出去,接着填充下一块,以此类推直到stream完成传输。
    • 但是如果你的网速很慢的话,处理完第一组数据,下一组还没到,那么屏幕上就会有一个loading图片,或者文字"视频正在缓冲中...",意味着在buffer缓冲区正在聚集足够多的数据,或者等待更多的数据到达缓冲区。直到buffer填满足够多的数据,再开始处理数据,将视频显示出来。在播放视频的同时,后续的数据会陆续到达,并在缓冲区等待。如果当前视频数据播放完毕,buffer区又没填满的话,那么又会继续显示loading图像了。
    • 这就是Buffer!
    • buffer的原始定义就是这样:在buffer缓冲区我们可以操作流形式的二进制数据。我们可以对一列二进制数据进行哪些类型的操作呢?Node.js中的Buffer实现给我们提供了一系列可使用的API,我们接下来看看。

    操作Buffer

    • 你甚至可以创建一个属于你的buffer缓冲区!否则node.js会在流中自动帮你创建buffer,有意思吧?我们来创建一个试试。
    • 根据你想实现的东西,这里有不同的创建buffer的方法,让我们来看看
    // 创建一个大小为10的空buffer
    // 这个buffer只能容纳10字节
    const buf1 = Buffer.alloc(10);
    // 创建一个带有内容的buffer
    const buf2 = Buffer.from("hello buffer");
    
    • 一旦buffer创建好了,我们就可以开始与它交互了。
    // 查看buffer的结构
    buf1.toJSON()
    // { type: 'Buffer', data: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }
    // 一个空的buffer
    buf2.toJSON()
    // { type: 'Buffer',
         data: [ 
           104, 101, 108, 108, 111, 32, 98, 117, 102, 102, 101, 114 
         ] 
       }
    // toJSON方法以字符的Unicode Code Points来表示数据
    // 查看buffer的大小
    buf1.length // 10
    buf2.length // 12. 创建时基于初始内容自动分配buffer大小
    // 写数据到buffer中
    buf1.write("Buffer really rocks!") 
    
    // 解码一个buffer
    buf1.toString() // 'Buffer rea'
    //啊哦,因为buf1的大小为10,所以无法容纳剩余的数据。
    
    • 以上就是对buffer的一部分操作,更多内容参考node的官方文档。
    • 在最后,我给你留下一个挑战,去阅读zlib.js的源码,他是一个Node.js核心库,去看一下buffer操作二进制流数据的原理。这些最后转换成zip压缩的文件。

    相关文章

      网友评论

          本文标题:想要更加了解node.js中的Buffer吗?来看看这个

          本文链接:https://www.haomeiwen.com/subject/xltfiftx.html