您好,欢迎访问一九零五行业门户网

深入了解Node中的Buffer

在 stream 篇结中,我们留下了一个问题,下述代码输出的 chunk 是一个什么东西?
通过打印,我们发现 chunk 是 buffer 对象,其中的元素是16进制的两位数,即0~255的数值。【相关教程推荐:nodejs视频教程、编程教学】
说明在 stream 中流动的数据就是 buffer,那下面就让我们来探究一下 buffer 的真实面目!
? node 中为什么要引入 buffer?
最开始的时候 js 只在浏览器端运行,对于 unicode 编码的字符串容易处理,但是对于二进制和非 unicode 编码的字符串处理困难。并且二进制是计算机最底层的数据格式,视频/音频/程序/网络包都是以二进制来存储的。所以 node 需要引入一个对象来操作二进制,因此 buffer 诞生了,用于 tcp流/文件系统等操作处理二进制字节。
由于 buffer 在 node 中过于常用,所以在 node 启动的时候已经引入了 buffer,无需使用 require()
arraybuffer是什么arraybuffer 是内存之中的一段二进制数据,本身不能够操作内存,需要通过typedarray 对象或者 dataview 来操作。将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容,其部署了数组接口,可以使用数组的方式来操作数据
typedarray 视图最常用的是 typearray 视图,用于读写简单类型的 arraybuffer,比如 uint8array(无符号8位整数)数组视图, int16array(16位整数)数组视图
和 buffer 的关系nodejs 中的 buffer 类其实是 uint8array 的实现。
buffer 结构buffer 是一个类似 array 的对象,但是它主要用于操作字节
模块结构buffer 是 js 和 c++ 结合的模块,性能部分都由 c++ 实现,非性能部分都是 js 实现的
buffer 所占用的内存不是由 v8 分配的,属于堆外内存。
对象结构buffer 对象类似数组,其元素是16进制的两位数,即0~255的数值
从这个例子能够看出,不同字符在 buffer 中占据的字节是不一样的,在 utf-8 编码下,中文占据3个字节,英文和半角标号占用1个字节
? 输入的元素是小数/负数/超出255会发生什么事情?
对于上述这种情况,buffer 的处理为:
给元素的赋值小于0, 就将该值逐次加256,直到得到一个0到255之间的整数如果得到的数值大于255,就逐次减256,直到得到0~255区间内的数值如果是小数,只保留整数部分buffer 里面为什么展示的是16进制
其实在内存存储的依旧是二进制数,只是 buffer 在显示这内存数据的时候采用了16进制
大小为2字节的 buffer,一共有16 bit ,比如是00000001 00100011,如果直接这样显示不太方便就转成为了16进制<buffer 01, 23>
buffer 的创建buffer.alloc 和 buffer.allocunsafe创建固定大小的 buffer
buffer.alloc(size [, fill [, encoding]])size 新 buffer 的所需长度fill 用于预填充新 buffer 的值。默认值: 0encoding 如果 fill 是一个字符串,则这是它的字符编码。默认值: utf8
buffer.allocunsafe(size)分配一个大小为 size 字节的 buffer,allocunsafe 执行速度比 alloc 快,我们发现其结果并不像 buffer.alloc 那样都初始化为 00
当调用 allocunsafe 时分配的内存段尚未初始化,这样分配内存速度很块,但分配到的内存片段可能包含旧数据。如果在使用的时候不覆盖这些旧数据就可能造成内存泄露,虽然速度快,尽量避免使用
buffer 模块会预分配一个内部的大小为 buffer.poolsize 的 buffer 实例,作为快速分配的内存池,用于使用 allocunsafe 创建新的 buffer 实例
buffer.from根据内容直接创建buffer
buffer.from(string [, encoding])buffer.from(array)buffer.from(buffer)
buffer.allocunsafe 的内存机制为了高效使用申请来的内存,node.js 采用了 slab 机制进行预先申请、事后分配,是一种动态的管理机制
使用 buffer.alloc(size) 传入一个指定的 size 就会申请一块固定大小的内存区域,slab 具有如下三种状态
full: 完全分配状态partial:部分分配状态empty:没有被分配状态node.js 使用8 kb 为界限来区分是小对象还是大对象
buffer 在创建的时候大小就已经被确定了且无法调整!
分配小对象如果分配的对象小于 8kb,node 会按着小对象的方式来进行分配
buffer 的分配过程中主要使用一个局部变量 pool 作为中间处理对象,处于分配状态的 slab 单元都指向它。以下是分配一个全新的 slab 单元的操作,它将会新申请的 slowbuffer 对象指向它
一个 slab 单元
分配一个 2kb 大小的 buffer创建一个 2kb 的 buffer后,一个 slab 单元内存如下:
这个分配过程是由 allocate 方法完成
当我们创建了一个 2kb 的 buffer 之后,当前 slab 状态为 partial
再次创建 buffer 的时候,会去判断当前 slab 剩余空间是否足够。如果足够,使用剩余空间,并更新 slab 的分配状态
如果 slab 空间不够,就会构建新的 slab,原 slab 中剩余的空间造成浪费
分配大对象如果有超过 8kb 的 buffer,直接会走到 creatunsafebuffer 函数,分配一个 slab 单元,这个 slab 单元将会被这个大 buffer 对象独占
allocate 分配机制如图
buffer 的内存分配机制
buffer 和字符编码通过使用字符编码,可实现 buffer 实例与 javascript 字符串之间的相互转换
node 中目前支持 utf8、ucs2、utf16le、latin1、ascii、base64、hex、base64url 八种编码方式,具体实现
针对于每一种不同的编码方案都会用实现一系列 api,返回会有不同的结果,node.js 会根据传入的 encoding 来返回不同的对象
buffer 和字符串的转换字符串转 buffer主要通过上述讲的 buffer.from 方法,默认的 encoding 方式为 utf-8
buffer 转字符串
? 为什么会出现乱码呢?如何解决这个问题呢?
按着读取来说,我们每次读取的长度为4,chunk输出如下
对于data += chunk等价于data = data.tostring + chunk.tostring
由于一个中文占据三个字节,第一个 chunk 中的第四个字节会显示乱码,第二个 chunk 的第一第二个字节也无法形成文字等等,所以会展示乱码问题
更多node相关知识,请访问:nodejs 教程!
以上就是深入了解node中的buffer的详细内容。
其它类似信息

推荐信息