详解nodeJS之二进制buffer对象(2)

var buf1 = Buffer.from('this is a tést'); console.log(buf1.toString());//this is a tést console.log(buf1.toString('ascii'));//this is a tC)st var buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); console.log(buf2.toString());//this is a tést

4、new Buffer(arrayBuffer[, byteOffset [, length]])。参数arrayBuffer <ArrayBuffer> 一个 ArrayBuffer,或一个 TypedArray 的 .buffer 属性;byteOffset <Integer> 开始拷贝的索引。默认为 0;length <Integer> 拷贝的字节数。默认为 arrayBuffer.length - byteOffset 

var arr = new Uint16Array(2); arr[0] = 5000; arr[1] = 4000; var buf = new Buffer(arr.buffer); console.log(buf);//<Buffer 88 13 a0 0f> arr[1] = 6000; console.log(buf);//<Buffer 88 13 70 17>

【Buffer.from(arrayBuffer[, byteOffset [, length]])】

在新版本中,由Buffer.from(arrayBuffer[, byteOffset [, length]])方法替代

var arr = new Uint16Array(2); arr[0] = 5000; arr[1] = 4000; var buf = Buffer.from(arr.buffer); console.log(buf);//<Buffer 88 13 a0 0f> arr[1] = 6000; console.log(buf);//<Buffer 88 13 70 17>

类数组

Buffer对象类似于数组,它的元素为16进制的两位数,即0到255的数值

console.log(Buffer.from('test'));//<Buffer 74 65 73 74>

【长度】

不同编码的字符串占用的元素个数各不相同,中文字在UTF-8编码下占用3个元素,字母和半角标点符号占用1个元素

var buf = Buffer.from('match'); console.log(buf.length);//5 var buf = Buffer.from('火柴'); console.log(buf.length);//6

【下标】

Buffer受Array类型的影响很大,可以访问length属性得到长度,也可以通过下标访问元素

var buf = Buffer.alloc(10); console.log(buf.length); // => 10

上述代码分配了一个长10字节的Buffer对象。我们可以通过下标对它进行赋值

buf[0] = 100; console.log(buf[0]); // => 100

要注意的是,给元素的赋值如果小于0,就将该值逐次加256,直到得到一个0到255之间的整数。如果得到的数值大于255,就逐次减256,直到得到0~255区间内的数值。如果是小数,舍弃小数部分,只保留整数部分 

buf[0] = -100; console.log(buf[0]); // 156 buf[1] = 300; console.log(buf[1]); // 44 buf[2] = 3.1415; console.log(buf[2]); // 3

【fromcharcode】

通常地,创建的buffer对象的内容是其uft-8字符编码

var buf = Buffer.from('match'); console.log(buf); //<Buffer 6d 61 74 63 68>

如果要访问其对应的字符,则需要使用字符串的fromCharCode()方法

console.log(String.fromCharCode(buf[0]));//'m'

内存分配

Buffer对象的内存分配不是在V8的堆内存中,而是在Node的C++层面实现内存的申请的。因为处理大量的字节数据不能采用需要一点内存就向操作系统申请一点内存的方式,这可能造成大量的内存申请的系统调用,对操作系统有一定压力。为此Node在内存的使用上应用的是在C++层面申请内存、在JavaScript中分配内存的策略

为了高效地使用申请来的内存,Node采用了slab分配机制。slab是一种动态内存管理机制,最早诞生于SunOS操作系统(Solaris)中,目前在一些*nix操作系统中有广泛的应用,如FreeBSD和Linux。简单而言,slab就是一块申请好的固定大小的内存区域。slab具有如下3种状态:full:完全分配状态;partial:部分分配状态;empty:没有被分配状态

当我们需要一个Buffer对象,可以通过以下方式分配指定大小的Buffer对象:

new Buffer(size);//旧 Buffer.alloc(size);//新

【poolSize】

poolSize属性是用于决定预分配的、内部 Buffer 实例池的大小的字节数。默认地,Node以8KB为界限来区分Buffer是大对象还是小对象:

Buffer.poolSize = 8 * 1024;

这个8KB的值也就是每个slab的大小值,在JavaScript层面,以它作为单位单元进行内存的分配

1、分配小Buffer对象

如果指定Buffer的大小少于8KB,Node会按照小对象的方式进行分配。Buffer的分配过程中主要使用一个局部变量pool作为中间处理对象,处于分配状态的slab单元都指向它。以下是分配一个全新的slab单元的操作,它会将新申请的SlowBuffer对象指向它:

var pool; function allocPool() { pool = new SlowBuffer(Buffer.poolSize); pool.used = 0; }

构造小Buffer对象时的代码如下:

new Buffer(1024);//旧 Buffer.alloc(1024);//新

这次构造将会去检查pool对象,如果pool没有被创建,将会创建一个新的slab单元指向它:

if (!pool || pool.length - pool.used < this.length) allocPool();

同时当前Buffer对象的parent属性指向该slab,并记录下是从这个slab的哪个位置(offset)开始使用的,slab对象自身也记录被使用了多少字节,代码如下:

this.parent = pool; this.offset = pool.used; pool.used += this.length; if (pool.used & 7) pool.used = (pool.used + 8) & ~7;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wyxxjd.html