Buffer是什么?Buffer存在于全局对象之上,无需引入模块即可使用,可见其重要性。可以理解Buffer是在内存中开辟的一块区域,用于存放二进制数据。Buffer开辟的是堆外内存。Buffer的应用场景有哪些?flow怎么理解flow?流是数据的集合(类似于数据和字符串),但是流的数据不能一次性获取,也不会全部加载到内存中。因此,流非常适合大数据处理和间歇性地向外部源返回块。流的生产者和消费者之间的速度通常是不一致的,所以需要一个缓冲区来临时存储一些数据。缓冲区大小由highWaterMark参数指定,默认为16Kb。存储需要大量内存的数据Buffer对象占用的内存空间不计入N??ode.js进程的内存空间限制,所以可以用来存储大对象,但是对象的大小还是有限的。一般来说,32位系统1G左右,64位系统2G左右。如何创建Buffer除了流自动隐式创建Buffer外,还可以手动创建Buffer,如下:Buffer中存储的数据已经确定Buffer.from(obj)//Thetypesobj支持的有string,buffer,arrayBuffer,array,orarray-likeobject注意:Buffer.from不支持传入数字,如下:Buffer.from(1234);buffer.js:208thrownewerrors.TypeError(^TypeError[ERR_INVALID_ARG_TYPE]:The"value"argumentmustnotbeoftypenumber.ReceivedtypenumberatFunction.from(buffer.js:208:11)...如果要传入数字,可以传入一个array:constbuf=Buffer.from([1,2,3,4]);console.log(buf);//但是这个方法有个问题,当存储不同的值时,buffer中记录的二进制数据会是一样的,如下所示:constbuf2=Buffer.from([127,-1]);console.log(buf2);constbuf3=Buffer.from([127,255]);console.log(buf3);console.log(buf3.equals(buf2));//true当要记录的数字集合都在0到255范围内(readUInt8读取),或者都在-128到范围内127(readInt8读取),那就没问题了,否则强烈不建议使用Buffer.from来保存一组数字。因为读取不同的方法应该调用不同的数字。Buffer存储数据不确定Buffer.alloc、Buffer.allocUnsafe、Buffer.allocUnsafeSlowBuffer.alloc会将分配的内存填充为0,所以比后两者慢,但也更安全。当然你也可以使用--zero-fill-buffers标志让allocUnsafe和allocUnsafeSlow在分配内存后填充0值。node--zero-fill-buffersindex.js当分配的空间小于4KB时,allocUnsafe会直接从之前预分配的Buffer中分片空间,所以速度比allocUnsafeSlow快。当分配的空间大于或等于4KB时,两者的速度差别不大。//分配空间等于functioncreateBuffer(fn,size){console.time('buf-'+fn);对于(vari=0;i<100000;i++){Buffer[fn](size);}安慰。timeEnd('buf-'+fn);}createBuffer('alloc',4096);createBuffer('allocUnsafe',4096);createBuffer('allocUnsafeSlow',4096);//输出buf-alloc:294.002msbuf-allocUnsafe:224.072msbuf-allocUnsafeSlow:209.22msfunctioncreateBuffer(fn,size){console.time('buf-'+fn);对于(vari=0;i<100000;i++){Buffer[fn](size);}console.timeEnd('buf-'+fn);}createBuffer('alloc',4095);createBuffer('allocUnsafe',4095);createBuffer('allocUnsafeSlow',4095);//输出buf-alloc:296.965msbuf-allocUnsafe:135.877msbuf-allocUnsafeSlow:205.225ms需要注意一点:新的Buffer(xxxx)方法不再推荐使用Buffer使用buffer来转换字符串constbuf=Buffer.from('test');console.日志(buf.toString('utf8'));//testconsole.log(buf.toString('utf8',0,2));//tebuffer到jsonconstbuf=Buffer.from([0x1,0x2,0x3,0x4,0x5]);console.log(buf.toJSON());//{type:'Buffer',data:[1,2,3,4,5]}缓冲区裁剪,裁剪后返回的新缓冲区指向与原缓冲区相同的内存块buf.slice([start[,end]])start起始位置end结束位置(不包括)例子:varbuf1=Buffer.from('test');varbuf2=buf1.slice(1,3).fill('xx');console.log("buf2内容:"+buf2.toString());//xxconsole.log("buf1内容:"+buf1.toString());//txxtbuffer复制,buffer不同于数组,buffer的长度一旦确定,就不会改变,所以当复制的sourcebuffer大于targetbuffer时,只会复制部分值buf.copy(target[,targetStart[,sourceStart[,sourceEnd]]])示例:varbuf1=Buffer.from('abcdefghijkl');varbuf2=Buffer.from('ABCDEF');buf1.copy(buf2,1);console.log(buf2.toString());//abcdefbuffer相等判断,比较的是二进制值buf.equals(otherBuffer)例子:constbuf1=Buffer.from('ABC');constbuf2=Buffer.from('414243','hex');console.log(buf1.equals(buf2));//true除了equals之外,compare其实也可以用来判断是否相等(结果为0时相等),但是compare的主要作用是比较数组中的buffer实例进行排序缓冲区是否包含特定值buf.includes(value[,byteOffset][,encoding])buf.indexOf(value[,byteOffset][,encoding])示例:constbuf=Buffer.from('thisisabuffer');console.log(buf.includes('this'));//trueconsole.log(buf.indexOf('this'));//0写入读取值写入方法:write{Double|浮动|整数16|诠释32|单位16|UInt32}{BE|LE}(值,偏移量)写入{Int|UInt}{BE|LE}(value,offset,bytelength)//这个方法提供了更灵活的位数来表示数据(比如3位,5位)write{Int8|Unit8}(value,offset)读方法:write{Double|浮动|整数16|整数32|单位16|UInt32}{BE|LE}(偏移量)读取{Int||LE}(offset,byteLength)read{Int8|Unit8}(offset)Double,Float,Int16,Int32,UInt16,UInt32不仅要判断代表数字的位数,还要判断是否包含负数,所以定义不同的数据范围。同时,由于表示数字的位数超过了8位,不能用一个字节来表示,所以涉及到计算机的字节序区分(big-endian字节序和little-endian字节序)。big-endian和small-endian的区别可以这样理解:value的高位在buffer的起始位置,value的低位起始位置是littleendian。constbuf=Buffer.allocUnsafe(2);buf.writeInt16BE(256,0)console.log(buf);//<缓冲区0100>buf.writeInt16LE(256,0)console.log(buf);//
